Revision: 6584
Author: [email protected]
Date: Wed Feb 2 07:49:30 2011
Log: Merge r6576 and r6581 from bleeding_edge to 3.0 branch.
This is a partial fix for V8 issue 1079, affecting use of the arguments
property of optimized functions.
Review URL: http://codereview.chromium.org/6334055
http://code.google.com/p/v8/source/detail?r=6584
Added:
/branches/3.0/test/mjsunit/regress/regress-1079.js
Modified:
/branches/3.0/src/accessors.cc
/branches/3.0/src/arm/deoptimizer-arm.cc
/branches/3.0/src/arm/lithium-arm.cc
/branches/3.0/src/arm/lithium-arm.h
/branches/3.0/src/arm/lithium-codegen-arm.cc
/branches/3.0/src/deoptimizer.h
/branches/3.0/src/hydrogen-instructions.h
/branches/3.0/src/hydrogen.cc
/branches/3.0/src/ia32/deoptimizer-ia32.cc
/branches/3.0/src/ia32/lithium-codegen-ia32.cc
/branches/3.0/src/ia32/lithium-ia32.cc
/branches/3.0/src/ia32/lithium-ia32.h
/branches/3.0/src/safepoint-table.cc
/branches/3.0/src/safepoint-table.h
/branches/3.0/src/x64/deoptimizer-x64.cc
/branches/3.0/src/x64/lithium-codegen-x64.cc
/branches/3.0/src/x64/lithium-x64.cc
/branches/3.0/src/x64/lithium-x64.h
/branches/3.0/test/cctest/cctest.status
=======================================
--- /dev/null
+++ /branches/3.0/test/mjsunit/regress/regress-1079.js Wed Feb 2 07:49:30
2011
@@ -0,0 +1,45 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Getting the arguments property of an optimized function should not
crash,
+// even if called through our optimized version of
Function.prototype.apply.
+
+function optimized() {
+ return unoptimized.apply(null, arguments);
+}
+
+// It's not crucial that this is unoptimized.
+function unoptimized() {
+ with ({}) {
+ return optimized.arguments;
+ }
+}
+
+for (var i = 0; i < 100000; ++i) {
+ assertEquals(3, optimized(1, 2, 3).length);
+}
+
=======================================
--- /branches/3.0/src/accessors.cc Mon Jan 10 00:15:37 2011
+++ /branches/3.0/src/accessors.cc Wed Feb 2 07:49:30 2011
@@ -675,46 +675,36 @@
int inlined_frame_index,
Vector<SlotRef>* args_slots) {
AssertNoAllocation no_gc;
-
int deopt_index = AstNode::kNoNumber;
-
DeoptimizationInputData* data =
static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
-
TranslationIterator it(data->TranslationByteArray(),
data->TranslationIndex(deopt_index)->value());
-
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
ASSERT(opcode == Translation::BEGIN);
int frame_count = it.Next();
-
USE(frame_count);
ASSERT(frame_count > inlined_frame_index);
-
int frames_to_skip = inlined_frame_index;
while (true) {
opcode = static_cast<Translation::Opcode>(it.Next());
-
// Skip over operands to advance to the next opcode.
it.Skip(Translation::NumberOfOperandsFor(opcode));
-
if (opcode == Translation::FRAME) {
if (frames_to_skip == 0) {
- // We reached frame corresponding to inlined function in question.
- // Process translation commands for arguments.
-
- // Skip translation command for receiver.
+ // We reached the frame corresponding to the inlined function
+ // in question. Process the translation commands for the
+ // arguments.
+ //
+ // Skip the translation command for the receiver.
it.Skip(Translation::NumberOfOperandsFor(
static_cast<Translation::Opcode>(it.Next())));
-
// Compute slots for arguments.
for (int i = 0; i < args_slots->length(); ++i) {
(*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame);
}
-
return;
}
-
frames_to_skip--;
}
}
@@ -727,16 +717,11 @@
JavaScriptFrame* frame,
Handle<JSFunction> inlined_function,
int inlined_frame_index) {
-
int args_count = inlined_function->shared()->formal_parameter_count();
-
ScopedVector<SlotRef> args_slots(args_count);
-
ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots);
-
Handle<JSObject> arguments =
Factory::NewArgumentsObject(inlined_function, args_count);
-
Handle<FixedArray> array = Factory::NewFixedArray(args_count);
for (int i = 0; i < args_count; ++i) {
Handle<Object> value = args_slots[i].GetValue();
@@ -766,39 +751,43 @@
if (functions[i] != *function) continue;
if (i > 0) {
- // Function in question was inlined.
+ // The function in question was inlined. Inlined functions have
the
+ // correct number of arguments and no allocated arguments object,
so
+ // we can construct a fresh one by interpreting the function's
+ // deoptimization input data.
return ConstructArgumentsObjectForInlinedFunction(frame, function,
i);
- } else {
+ }
+
+ if (!frame->is_optimized()) {
// If there is an arguments variable in the stack, we return that.
- int index = function->shared()->scope_info()->
- StackSlotIndex(Heap::arguments_symbol());
+ Handle<SerializedScopeInfo> info(function->shared()->scope_info());
+ int index = info->StackSlotIndex(Heap::arguments_symbol());
if (index >= 0) {
- Handle<Object> arguments =
- Handle<Object>(frame->GetExpression(index));
+ Handle<Object> arguments(frame->GetExpression(index));
if (!arguments->IsArgumentsMarker()) return *arguments;
}
-
- // If there isn't an arguments variable in the stack, we need to
- // find the frame that holds the actual arguments passed to the
- // function on the stack.
- it.AdvanceToArgumentsFrame();
- frame = it.frame();
-
- // Get the number of arguments and construct an arguments object
- // mirror for the right frame.
- const int length = frame->GetProvidedParametersCount();
- Handle<JSObject> arguments = Factory::NewArgumentsObject(function,
- length);
- Handle<FixedArray> array = Factory::NewFixedArray(length);
-
- // Copy the parameters to the arguments object.
- ASSERT(array->length() == length);
- for (int i = 0; i < length; i++) array->set(i,
frame->GetParameter(i));
- arguments->set_elements(*array);
-
- // Return the freshly allocated arguments object.
- return *arguments;
- }
+ }
+
+ // If there is no arguments variable in the stack or we have an
+ // optimized frame, we find the frame that holds the actual arguments
+ // passed to the function.
+ it.AdvanceToArgumentsFrame();
+ frame = it.frame();
+
+ // Get the number of arguments and construct an arguments object
+ // mirror for the right frame.
+ const int length = frame->GetProvidedParametersCount();
+ Handle<JSObject> arguments = Factory::NewArgumentsObject(function,
+ length);
+ Handle<FixedArray> array = Factory::NewFixedArray(length);
+
+ // Copy the parameters to the arguments object.
+ ASSERT(array->length() == length);
+ for (int i = 0; i < length; i++) array->set(i,
frame->GetParameter(i));
+ arguments->set_elements(*array);
+
+ // Return the freshly allocated arguments object.
+ return *arguments;
}
functions.Rewind(0);
}
=======================================
--- /branches/3.0/src/arm/deoptimizer-arm.cc Tue Jan 25 06:06:47 2011
+++ /branches/3.0/src/arm/deoptimizer-arm.cc Wed Feb 2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -37,6 +37,14 @@
int Deoptimizer::table_entry_size_ = 16;
+
+int Deoptimizer::patch_size() {
+ const int kCallInstructionSizeInWords = 3;
+ return kCallInstructionSizeInWords * Assembler::kInstrSize;
+}
+
+
+
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
AssertNoAllocation no_allocation;
@@ -51,6 +59,8 @@
// For each return after a safepoint insert an absolute call to the
// corresponding deoptimization entry.
+ ASSERT(patch_size() % Assembler::kInstrSize == 0);
+ int call_size_in_words = patch_size() / Assembler::kInstrSize;
unsigned last_pc_offset = 0;
SafepointTable table(function->code());
for (unsigned i = 0; i < table.length(); i++) {
@@ -73,14 +83,13 @@
#endif
last_pc_offset = pc_offset;
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- const int kCallInstructionSizeInWords = 3;
- CodePatcher patcher(code->instruction_start() + pc_offset +
gap_code_size,
- kCallInstructionSizeInWords);
+ last_pc_offset += gap_code_size;
+ CodePatcher patcher(code->instruction_start() + last_pc_offset,
+ call_size_in_words);
Address deoptimization_entry = Deoptimizer::GetDeoptimizationEntry(
deoptimization_index, Deoptimizer::LAZY);
patcher.masm()->Call(deoptimization_entry, RelocInfo::NONE);
- last_pc_offset +=
- gap_code_size + kCallInstructionSizeInWords *
Assembler::kInstrSize;
+ last_pc_offset += patch_size();
}
}
=======================================
--- /branches/3.0/src/arm/lithium-arm.cc Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/arm/lithium-arm.cc Wed Feb 2 07:49:30 2011
@@ -655,16 +655,16 @@
LInstruction*
LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
LInstruction* instr, int ast_id) {
- ASSERT(instructions_pending_deoptimization_environment_ == NULL);
+ ASSERT(instruction_pending_deoptimization_environment_ == NULL);
ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
- instructions_pending_deoptimization_environment_ = instr;
+ instruction_pending_deoptimization_environment_ = instr;
pending_deoptimization_ast_id_ = ast_id;
return instr;
}
void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
- instructions_pending_deoptimization_environment_ = NULL;
+ instruction_pending_deoptimization_environment_ = NULL;
pending_deoptimization_ast_id_ = AstNode::kNoNumber;
}
@@ -1461,6 +1461,13 @@
return AssignEnvironment(new
LBoundsCheck(UseRegisterAtStart(instr->index()),
UseRegister(instr->length())));
}
+
+
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+ // The control instruction marking the end of a block that completed
+ // abruptly (e.g., threw an exception). There is nothing specific to do.
+ return NULL;
+}
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
@@ -1837,7 +1844,7 @@
if (pending_deoptimization_ast_id_ == instr->ast_id()) {
LInstruction* result = new LLazyBailout;
result = AssignEnvironment(result);
- instructions_pending_deoptimization_environment_->
+ instruction_pending_deoptimization_environment_->
set_deoptimization_environment(result->environment());
ClearInstructionPendingDeoptimizationEnvironment();
return result;
=======================================
--- /branches/3.0/src/arm/lithium-arm.h Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/arm/lithium-arm.h Wed Feb 2 07:49:30 2011
@@ -1855,7 +1855,7 @@
argument_count_(0),
allocator_(allocator),
position_(RelocInfo::kNoPosition),
- instructions_pending_deoptimization_environment_(NULL),
+ instruction_pending_deoptimization_environment_(NULL),
pending_deoptimization_ast_id_(AstNode::kNoNumber) { }
// Build the sequence for the graph.
@@ -1989,7 +1989,7 @@
int argument_count_;
LAllocator* allocator_;
int position_;
- LInstruction* instructions_pending_deoptimization_environment_;
+ LInstruction* instruction_pending_deoptimization_environment_;
int pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
=======================================
--- /branches/3.0/src/arm/lithium-codegen-arm.cc Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/arm/lithium-codegen-arm.cc Wed Feb 2 07:49:30 2011
@@ -562,17 +562,11 @@
void LCodeGen::CallCode(Handle<Code> code,
RelocInfo::Mode mode,
LInstruction* instr) {
- if (instr != NULL) {
- LPointerMap* pointers = instr->pointer_map();
- RecordPosition(pointers->position());
- __ Call(code, mode);
- RegisterLazyDeoptimization(instr);
- } else {
- LPointerMap no_pointers(0);
- RecordPosition(no_pointers.position());
- __ Call(code, mode);
- RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
- }
+ ASSERT(instr != NULL);
+ LPointerMap* pointers = instr->pointer_map();
+ RecordPosition(pointers->position());
+ __ Call(code, mode);
+ RegisterLazyDeoptimization(instr);
}
@@ -585,15 +579,7 @@
RecordPosition(pointers->position());
__ CallRuntime(function, num_arguments);
- // Runtime calls to Throw are not supposed to ever return at the
- // call site, so don't register lazy deoptimization for these. We do
- // however have to record a safepoint since throwing exceptions can
- // cause garbage collections.
- if (!instr->IsThrow()) {
- RegisterLazyDeoptimization(instr);
- } else {
- RecordSafepoint(instr->pointer_map(),
Safepoint::kNoDeoptimizationIndex);
- }
+ RegisterLazyDeoptimization(instr);
}
@@ -2450,12 +2436,17 @@
__ b(ne, &loop);
__ bind(&invoke);
- // Invoke the function. The number of arguments is stored in receiver
- // which is r0, as expected by InvokeFunction.
- v8::internal::ParameterCount actual(receiver);
+ ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+ LPointerMap* pointers = instr->pointer_map();
+ LEnvironment* env = instr->deoptimization_environment();
+ RecordPosition(pointers->position());
+ RegisterEnvironmentForDeoptimization(env);
SafepointGenerator safepoint_generator(this,
- instr->pointer_map(),
-
Safepoint::kNoDeoptimizationIndex);
+ pointers,
+ env->deoptimization_index());
+ // The number of arguments is stored in receiver which is r0, as expected
+ // by InvokeFunction.
+ v8::internal::ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
}
@@ -3667,10 +3658,14 @@
Register object = ToRegister(instr->object());
Register key = ToRegister(instr->key());
__ Push(object, key);
- RecordPosition(instr->pointer_map()->position());
+ ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+ LPointerMap* pointers = instr->pointer_map();
+ LEnvironment* env = instr->deoptimization_environment();
+ RecordPosition(pointers->position());
+ RegisterEnvironmentForDeoptimization(env);
SafepointGenerator safepoint_generator(this,
- instr->pointer_map(),
-
Safepoint::kNoDeoptimizationIndex);
+ pointers,
+ env->deoptimization_index());
__ InvokeBuiltin(Builtins::DELETE, CALL_JS, &safepoint_generator);
}
=======================================
--- /branches/3.0/src/deoptimizer.h Tue Jan 25 06:06:47 2011
+++ /branches/3.0/src/deoptimizer.h Wed Feb 2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -128,6 +128,9 @@
static void VisitAllOptimizedFunctions(OptimizedFunctionVisitor*
visitor);
+ // The size in bytes of the code required at a lazy deopt patch site.
+ static int patch_size();
+
// Patch all stack guard checks in the unoptimized code to
// unconditionally call replacement_code.
static void PatchStackCheckCode(Code* unoptimized_code,
=======================================
--- /branches/3.0/src/hydrogen-instructions.h Wed Feb 2 02:08:20 2011
+++ /branches/3.0/src/hydrogen-instructions.h Wed Feb 2 07:49:30 2011
@@ -64,6 +64,7 @@
#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
+ V(AbnormalExit) \
V(AccessArgumentsAt) \
V(Add) \
V(ApplyArguments) \
@@ -834,12 +835,11 @@
};
-class HThrow: public HUnaryControlInstruction {
+class HAbnormalExit: public HControlInstruction {
public:
- explicit HThrow(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) { }
-
- DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
+ HAbnormalExit() : HControlInstruction(NULL, NULL) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
};
@@ -866,6 +866,20 @@
};
+class HThrow: public HUnaryOperation {
+ public:
+ explicit HThrow(HValue* value) : HUnaryOperation(value) {
+ SetAllSideEffects();
+ }
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
+};
+
+
class HChange: public HUnaryOperation {
public:
HChange(HValue* value,
@@ -989,7 +1003,7 @@
public:
HStackCheck() { }
- DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check")
+ DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
};
@@ -1831,6 +1845,7 @@
SetOperandAt(1, receiver);
SetOperandAt(2, length);
SetOperandAt(3, elements);
+ SetAllSideEffects();
}
virtual Representation RequiredInputRepresentation(int index) const {
@@ -1850,8 +1865,6 @@
DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
-
-
protected:
virtual void InternalSetOperandAt(int index, HValue* value) {
operands_[index] = value;
=======================================
--- /branches/3.0/src/hydrogen.cc Mon Jan 31 05:20:57 2011
+++ /branches/3.0/src/hydrogen.cc Wed Feb 2 07:49:30 2011
@@ -3556,9 +3556,11 @@
VISIT_FOR_VALUE(expr->exception());
HValue* value = environment()->Pop();
- HControlInstruction* instr = new HThrow(value);
+ HThrow* instr = new HThrow(value);
instr->set_position(expr->position());
- current_subgraph_->FinishExit(instr);
+ AddInstruction(instr);
+ AddSimulate(expr->id());
+ current_subgraph_->FinishExit(new HAbnormalExit);
}
=======================================
--- /branches/3.0/src/ia32/deoptimizer-ia32.cc Wed Feb 2 02:24:23 2011
+++ /branches/3.0/src/ia32/deoptimizer-ia32.cc Wed Feb 2 07:49:30 2011
@@ -37,9 +37,14 @@
namespace v8 {
namespace internal {
-
int Deoptimizer::table_entry_size_ = 10;
+
+int Deoptimizer::patch_size() {
+ return Assembler::kCallInstructionLength;
+}
+
+
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
AssertNoAllocation no_allocation;
@@ -77,11 +82,12 @@
#endif
last_pc_offset = pc_offset;
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- Address call_pc = code->instruction_start() + pc_offset +
gap_code_size;
- CodePatcher patcher(call_pc, Assembler::kCallInstructionLength);
+ last_pc_offset += gap_code_size;
+ Address call_pc = code->instruction_start() + last_pc_offset;
+ CodePatcher patcher(call_pc, patch_size());
Address entry = GetDeoptimizationEntry(deoptimization_index, LAZY);
patcher.masm()->call(entry, RelocInfo::NONE);
- last_pc_offset += gap_code_size + Assembler::kCallInstructionLength;
+ last_pc_offset += patch_size();
RelocInfo rinfo(call_pc + 1, RelocInfo::RUNTIME_ENTRY,
reinterpret_cast<intptr_t>(entry));
reloc_info_writer.Write(&rinfo);
=======================================
--- /branches/3.0/src/ia32/lithium-codegen-ia32.cc Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/ia32/lithium-codegen-ia32.cc Wed Feb 2 07:49:30 2011
@@ -37,6 +37,8 @@
namespace internal {
+// When invoking builtins, we need to record the safepoint in the middle of
+// the invoke instruction sequence generated by the macro assembler.
class SafepointGenerator : public PostCallGenerator {
public:
SafepointGenerator(LCodeGen* codegen,
@@ -366,17 +368,11 @@
void LCodeGen::CallCode(Handle<Code> code,
RelocInfo::Mode mode,
LInstruction* instr) {
- if (instr != NULL) {
- LPointerMap* pointers = instr->pointer_map();
- RecordPosition(pointers->position());
- __ call(code, mode);
- RegisterLazyDeoptimization(instr);
- } else {
- LPointerMap no_pointers(0);
- RecordPosition(no_pointers.position());
- __ call(code, mode);
- RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
- }
+ ASSERT(instr != NULL);
+ LPointerMap* pointers = instr->pointer_map();
+ RecordPosition(pointers->position());
+ __ call(code, mode);
+ RegisterLazyDeoptimization(instr);
// Signal that we don't inline smi code before these stubs in the
// optimizing code generator.
@@ -391,22 +387,12 @@
int num_arguments,
LInstruction* instr) {
ASSERT(instr != NULL);
+ ASSERT(instr->HasPointerMap());
LPointerMap* pointers = instr->pointer_map();
- ASSERT(pointers != NULL);
RecordPosition(pointers->position());
__ CallRuntime(function, num_arguments);
- // Runtime calls to Throw are not supposed to ever return at the
- // call site, so don't register lazy deoptimization for these. We do
- // however have to record a safepoint since throwing exceptions can
- // cause garbage collections.
- // BUG(3243555): register a lazy deoptimization point at throw. We need
- // it to be able to inline functions containing a throw statement.
- if (!instr->IsThrow()) {
- RegisterLazyDeoptimization(instr);
- } else {
- RecordSafepoint(instr->pointer_map(),
Safepoint::kNoDeoptimizationIndex);
- }
+ RegisterLazyDeoptimization(instr);
}
@@ -2145,11 +2131,16 @@
// Invoke the function.
__ bind(&invoke);
+ ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+ LPointerMap* pointers = instr->pointer_map();
+ LEnvironment* env = instr->deoptimization_environment();
+ RecordPosition(pointers->position());
+ RegisterEnvironmentForDeoptimization(env);
+ SafepointGenerator safepoint_generator(this,
+ pointers,
+ env->deoptimization_index());
ASSERT(receiver.is(eax));
v8::internal::ParameterCount actual(eax);
- SafepointGenerator safepoint_generator(this,
- instr->pointer_map(),
-
Safepoint::kNoDeoptimizationIndex);
__ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator);
}
@@ -3575,10 +3566,14 @@
} else {
__ push(ToOperand(key));
}
- RecordPosition(instr->pointer_map()->position());
+ ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+ LPointerMap* pointers = instr->pointer_map();
+ LEnvironment* env = instr->deoptimization_environment();
+ RecordPosition(pointers->position());
+ RegisterEnvironmentForDeoptimization(env);
SafepointGenerator safepoint_generator(this,
- instr->pointer_map(),
-
Safepoint::kNoDeoptimizationIndex);
+ pointers,
+ env->deoptimization_index());
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
}
=======================================
--- /branches/3.0/src/ia32/lithium-ia32.cc Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/ia32/lithium-ia32.cc Wed Feb 2 07:49:30 2011
@@ -658,16 +658,16 @@
LInstruction*
LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
LInstruction* instr, int ast_id) {
- ASSERT(instructions_pending_deoptimization_environment_ == NULL);
+ ASSERT(instruction_pending_deoptimization_environment_ == NULL);
ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
- instructions_pending_deoptimization_environment_ = instr;
+ instruction_pending_deoptimization_environment_ = instr;
pending_deoptimization_ast_id_ = ast_id;
return instr;
}
void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
- instructions_pending_deoptimization_environment_ = NULL;
+ instruction_pending_deoptimization_environment_ = NULL;
pending_deoptimization_ast_id_ = AstNode::kNoNumber;
}
@@ -1505,6 +1505,13 @@
return AssignEnvironment(new
LBoundsCheck(UseRegisterAtStart(instr->index()),
Use(instr->length())));
}
+
+
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+ // The control instruction marking the end of a block that completed
+ // abruptly (e.g., threw an exception). There is nothing specific to do.
+ return NULL;
+}
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
@@ -1875,10 +1882,11 @@
// If there is an instruction pending deoptimization environment create a
// lazy bailout instruction to capture the environment.
- if (pending_deoptimization_ast_id_ == instr->ast_id()) {
+ if (pending_deoptimization_ast_id_ != AstNode::kNoNumber) {
+ ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
LLazyBailout* lazy_bailout = new LLazyBailout;
LInstruction* result = AssignEnvironment(lazy_bailout);
- instructions_pending_deoptimization_environment_->
+ instruction_pending_deoptimization_environment_->
set_deoptimization_environment(result->environment());
ClearInstructionPendingDeoptimizationEnvironment();
return result;
=======================================
--- /branches/3.0/src/ia32/lithium-ia32.h Wed Jan 26 00:23:03 2011
+++ /branches/3.0/src/ia32/lithium-ia32.h Wed Feb 2 07:49:30 2011
@@ -1881,7 +1881,7 @@
argument_count_(0),
allocator_(allocator),
position_(RelocInfo::kNoPosition),
- instructions_pending_deoptimization_environment_(NULL),
+ instruction_pending_deoptimization_environment_(NULL),
pending_deoptimization_ast_id_(AstNode::kNoNumber) { }
// Build the sequence for the graph.
@@ -2015,7 +2015,7 @@
int argument_count_;
LAllocator* allocator_;
int position_;
- LInstruction* instructions_pending_deoptimization_environment_;
+ LInstruction* instruction_pending_deoptimization_environment_;
int pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
=======================================
--- /branches/3.0/src/safepoint-table.cc Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/safepoint-table.cc Wed Feb 2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -27,6 +27,7 @@
#include "safepoint-table.h"
+#include "deoptimizer.h"
#include "disasm.h"
#include "macro-assembler.h"
@@ -144,6 +145,14 @@
void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry)
{
+ // For lazy deoptimization we need space to patch a call after every
call.
+ // Ensure there is always space for such patching, even if the code ends
+ // in a call.
+ int target_offset = assembler->pc_offset() + Deoptimizer::patch_size();
+ while (assembler->pc_offset() < target_offset) {
+ assembler->nop();
+ }
+
// Make sure the safepoint table is properly aligned. Pad with nops.
assembler->Align(kIntSize);
assembler->RecordComment(";;; Safepoint table.");
=======================================
--- /branches/3.0/src/safepoint-table.h Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/safepoint-table.h Wed Feb 2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -215,11 +215,10 @@
unsigned GetCodeOffset() const;
// Define a new safepoint for the current position in the body.
- Safepoint DefineSafepoint(
- Assembler* assembler,
- Safepoint::Kind kind,
- int arguments,
- int deoptimization_index = Safepoint::kNoDeoptimizationIndex);
+ Safepoint DefineSafepoint(Assembler* assembler,
+ Safepoint::Kind kind,
+ int arguments,
+ int deoptimization_index);
// Update the last safepoint with the size of the code generated for the
gap
// following it.
=======================================
--- /branches/3.0/src/x64/deoptimizer-x64.cc Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/x64/deoptimizer-x64.cc Wed Feb 2 07:49:30 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -40,6 +40,12 @@
int Deoptimizer::table_entry_size_ = 10;
+
+int Deoptimizer::patch_size() {
+ return Assembler::kCallInstructionLength;
+}
+
+
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
AssertNoAllocation no_allocation;
@@ -72,12 +78,12 @@
#endif
last_pc_offset = pc_offset;
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- CodePatcher patcher(
- code->instruction_start() + pc_offset + gap_code_size,
- Assembler::kCallInstructionLength);
+ last_pc_offset += gap_code_size;
+ CodePatcher patcher(code->instruction_start() + last_pc_offset,
+ patch_size());
patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index,
LAZY),
RelocInfo::NONE);
- last_pc_offset += gap_code_size + Assembler::kCallInstructionLength;
+ last_pc_offset += patch_size();
}
}
#ifdef DEBUG
=======================================
--- /branches/3.0/src/x64/lithium-codegen-x64.cc Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/x64/lithium-codegen-x64.cc Wed Feb 2 07:49:30 2011
@@ -346,17 +346,11 @@
void LCodeGen::CallCode(Handle<Code> code,
RelocInfo::Mode mode,
LInstruction* instr) {
- if (instr != NULL) {
- LPointerMap* pointers = instr->pointer_map();
- RecordPosition(pointers->position());
- __ call(code, mode);
- RegisterLazyDeoptimization(instr);
- } else {
- LPointerMap no_pointers(0);
- RecordPosition(no_pointers.position());
- __ call(code, mode);
- RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
- }
+ ASSERT(instr != NULL);
+ LPointerMap* pointers = instr->pointer_map();
+ RecordPosition(pointers->position());
+ __ call(code, mode);
+ RegisterLazyDeoptimization(instr);
// Signal that we don't inline smi code before these stubs in the
// optimizing code generator.
=======================================
--- /branches/3.0/src/x64/lithium-x64.cc Fri Jan 28 00:04:38 2011
+++ /branches/3.0/src/x64/lithium-x64.cc Wed Feb 2 07:49:30 2011
@@ -655,14 +655,14 @@
LInstruction* instr, int ast_id) {
ASSERT(instructions_pending_deoptimization_environment_ == NULL);
ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
- instructions_pending_deoptimization_environment_ = instr;
+ instruction_pending_deoptimization_environment_ = instr;
pending_deoptimization_ast_id_ = ast_id;
return instr;
}
void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
- instructions_pending_deoptimization_environment_ = NULL;
+ instruction_pending_deoptimization_environment_ = NULL;
pending_deoptimization_ast_id_ = AstNode::kNoNumber;
}
@@ -1326,6 +1326,13 @@
Abort("Unimplemented: %s", "DoBoundsCheck");
return NULL;
}
+
+
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+ // The control instruction marking the end of a block that completed
+ // abruptly (e.g., threw an exception). There is nothing specific to do.
+ return NULL;
+}
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
@@ -1663,7 +1670,7 @@
if (pending_deoptimization_ast_id_ == instr->ast_id()) {
LLazyBailout* lazy_bailout = new LLazyBailout;
LInstruction* result = AssignEnvironment(lazy_bailout);
- instructions_pending_deoptimization_environment_->
+ instruction_pending_deoptimization_environment_->
set_deoptimization_environment(result->environment());
ClearInstructionPendingDeoptimizationEnvironment();
return result;
=======================================
--- /branches/3.0/src/x64/lithium-x64.h Wed Jan 26 00:23:03 2011
+++ /branches/3.0/src/x64/lithium-x64.h Wed Feb 2 07:49:30 2011
@@ -1847,7 +1847,7 @@
argument_count_(0),
allocator_(allocator),
position_(RelocInfo::kNoPosition),
- instructions_pending_deoptimization_environment_(NULL),
+ instruction_pending_deoptimization_environment_(NULL),
pending_deoptimization_ast_id_(AstNode::kNoNumber) { }
// Build the sequence for the graph.
@@ -1981,7 +1981,7 @@
int argument_count_;
LAllocator* allocator_;
int position_;
- LInstruction* instructions_pending_deoptimization_environment_;
+ LInstruction* instruction_pending_deoptimization_environment_;
int pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
=======================================
--- /branches/3.0/test/cctest/cctest.status Fri Jan 28 00:04:38 2011
+++ /branches/3.0/test/cctest/cctest.status Wed Feb 2 07:49:30 2011
@@ -51,9 +51,6 @@
test-serialize/TestThatAlwaysFails: FAIL
test-serialize/DependentTestThatAlwaysFails: FAIL
-# BUG(1079)
-test-api/CaptureStackTraceForUncaughtException: PASS || FAIL
-
##############################################################################
[ $arch == x64 ]
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev