Remove the forward-bailout stack from the non-optimizing compiler.

This was pretty heavyweight.  It was kept in just for a few corner cases
that assumed it was there.  We can work around them by making sure that the
expression in a reified test context is always really the expression that
was visited in that context; and by inspecting the context manually and
consing up a pair of extra AST IDs for the unusual case of unary not in a
value AST context.

R=fschneider@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/8386037

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9863 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2011-11-02 16:53:32 +00:00
parent 307b589e61
commit 4e4a901d96
8 changed files with 493 additions and 369 deletions

View File

@ -394,7 +394,7 @@ void FullCodeGenerator::TestContext::Plug(Variable* var) const {
ASSERT(var->IsStackAllocated() || var->IsContextSlot()); ASSERT(var->IsStackAllocated() || var->IsContextSlot());
// For simplicity we always test the accumulator register. // For simplicity we always test the accumulator register.
codegen()->GetVar(result_register(), var); codegen()->GetVar(result_register(), var);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -417,7 +417,7 @@ void FullCodeGenerator::StackValueContext::Plug(
void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, codegen()->PrepareForBailoutBeforeSplit(condition(),
true, true,
true_label_, true_label_,
false_label_); false_label_);
@ -452,7 +452,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, codegen()->PrepareForBailoutBeforeSplit(condition(),
true, true,
true_label_, true_label_,
false_label_); false_label_);
@ -511,7 +511,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
// For simplicity we always test the accumulator register. // For simplicity we always test the accumulator register.
__ Drop(count); __ Drop(count);
__ Move(result_register(), reg); __ Move(result_register(), reg);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -578,7 +578,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
void FullCodeGenerator::TestContext::Plug(bool flag) const { void FullCodeGenerator::TestContext::Plug(bool flag) const {
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, codegen()->PrepareForBailoutBeforeSplit(condition(),
true, true,
true_label_, true_label_,
false_label_); false_label_);
@ -681,7 +681,7 @@ void FullCodeGenerator::SetVar(Variable* var,
} }
void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
bool should_normalize, bool should_normalize,
Label* if_true, Label* if_true,
Label* if_false) { Label* if_false) {
@ -692,13 +692,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
Label skip; Label skip;
if (should_normalize) __ b(&skip); if (should_normalize) __ b(&skip);
PrepareForBailout(expr, TOS_REG);
ForwardBailoutStack* current = forward_bailout_stack_;
while (current != NULL) {
PrepareForBailout(current->expr(), state);
current = current->parent();
}
if (should_normalize) { if (should_normalize) {
__ LoadRoot(ip, Heap::kTrueValueRootIndex); __ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(r0, ip); __ cmp(r0, ip);
@ -2377,7 +2371,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
} }
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2389,7 +2384,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false, context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ tst(r0, Operand(kSmiTagMask)); __ tst(r0, Operand(kSmiTagMask));
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
@ -2397,7 +2392,8 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2409,7 +2405,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false, context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ tst(r0, Operand(kSmiTagMask | 0x80000000)); __ tst(r0, Operand(kSmiTagMask | 0x80000000));
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
@ -2417,7 +2413,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2442,14 +2439,15 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
__ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ b(lt, if_false); __ b(lt, if_false);
__ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(le, if_true, if_false, fall_through); Split(le, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2463,14 +2461,15 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
__ JumpIfSmi(r0, if_false); __ JumpIfSmi(r0, if_false);
__ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(ge, if_true, if_false, fall_through); Split(ge, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2486,7 +2485,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
__ tst(r1, Operand(1 << Map::kIsUndetectable)); __ tst(r1, Operand(1 << Map::kIsUndetectable));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(ne, if_true, if_false, fall_through); Split(ne, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -2494,8 +2493,8 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
ZoneList<Expression*>* args) { CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2574,12 +2573,13 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
__ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset)); __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
__ jmp(if_true); __ jmp(if_true);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2593,14 +2593,15 @@ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
__ JumpIfSmi(r0, if_false); __ JumpIfSmi(r0, if_false);
__ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2614,14 +2615,15 @@ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
__ JumpIfSmi(r0, if_false); __ JumpIfSmi(r0, if_false);
__ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2635,7 +2637,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
__ JumpIfSmi(r0, if_false); __ JumpIfSmi(r0, if_false);
__ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -2643,8 +2645,8 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
ASSERT(args->length() == 0); ASSERT(expr->arguments()->length() == 0);
Label materialize_true, materialize_false; Label materialize_true, materialize_false;
Label* if_true = NULL; Label* if_true = NULL;
@ -2667,14 +2669,15 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
__ bind(&check_frame_marker); __ bind(&check_frame_marker);
__ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
__ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
// Load the two objects into registers and perform the comparison. // Load the two objects into registers and perform the comparison.
@ -2690,14 +2693,15 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
__ pop(r1); __ pop(r1);
__ cmp(r0, r1); __ cmp(r0, r1);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
// ArgumentsAccessStub expects the key in edx and the formal // ArgumentsAccessStub expects the key in edx and the formal
@ -2711,9 +2715,8 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
ASSERT(args->length() == 0); ASSERT(expr->arguments()->length() == 0);
Label exit; Label exit;
// Get the number of formal parameters. // Get the number of formal parameters.
__ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
@ -2733,7 +2736,8 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
Label done, null, function, non_function_constructor; Label done, null, function, non_function_constructor;
@ -2793,7 +2797,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitLog(CallRuntime* expr) {
// Conditionally generate a log call. // Conditionally generate a log call.
// Args: // Args:
// 0 (literal string): The type of logging (corresponds to the flags). // 0 (literal string): The type of logging (corresponds to the flags).
@ -2801,6 +2805,7 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
// 1 (string): Format string. Access the string at argument index 2 // 1 (string): Format string. Access the string at argument index 2
// with '%2s' (see Logger::LogRuntime for all the formats). // with '%2s' (see Logger::LogRuntime for all the formats).
// 2 (array): Arguments to the format string. // 2 (array): Arguments to the format string.
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(args->length(), 3); ASSERT_EQ(args->length(), 3);
if (CodeGenerator::ShouldGenerateLog(args->at(0))) { if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2814,9 +2819,8 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
ASSERT(args->length() == 0); ASSERT(expr->arguments()->length() == 0);
Label slow_allocate_heapnumber; Label slow_allocate_heapnumber;
Label heapnumber_allocated; Label heapnumber_allocated;
@ -2868,9 +2872,10 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
// Load the arguments on the stack and call the stub. // Load the arguments on the stack and call the stub.
SubStringStub stub; SubStringStub stub;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 3); ASSERT(args->length() == 3);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2880,9 +2885,10 @@ void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
// Load the arguments on the stack and call the stub. // Load the arguments on the stack and call the stub.
RegExpExecStub stub; RegExpExecStub stub;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 4); ASSERT(args->length() == 4);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2893,9 +2899,9 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); // Load the object. VisitForAccumulatorValue(args->at(0)); // Load the object.
Label done; Label done;
@ -2911,8 +2917,9 @@ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
// Load the arguments on the stack and call the runtime function. // Load the arguments on the stack and call the runtime function.
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2922,9 +2929,9 @@ void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); // Load the object. VisitForStackValue(args->at(0)); // Load the object.
VisitForAccumulatorValue(args->at(1)); // Load the value. VisitForAccumulatorValue(args->at(1)); // Load the value.
__ pop(r1); // r0 = value. r1 = object. __ pop(r1); // r0 = value. r1 = object.
@ -2950,9 +2957,9 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(args->length(), 1); ASSERT_EQ(args->length(), 1);
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
@ -2962,9 +2969,9 @@ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
Label done; Label done;
@ -2980,9 +2987,9 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForAccumulatorValue(args->at(1)); VisitForAccumulatorValue(args->at(1));
@ -3027,9 +3034,9 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForAccumulatorValue(args->at(1)); VisitForAccumulatorValue(args->at(1));
@ -3076,9 +3083,9 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3088,9 +3095,9 @@ void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3100,10 +3107,11 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::SIN, TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::TAGGED); TranscendentalCacheStub::TAGGED);
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -3111,10 +3119,11 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::COS, TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::TAGGED); TranscendentalCacheStub::TAGGED);
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -3122,10 +3131,11 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::LOG, TranscendentalCacheStub stub(TranscendentalCache::LOG,
TranscendentalCacheStub::TAGGED); TranscendentalCacheStub::TAGGED);
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -3133,8 +3143,9 @@ void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
// Load the argument on the stack and call the runtime function. // Load the argument on the stack and call the runtime function.
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallRuntime(Runtime::kMath_sqrt, 1); __ CallRuntime(Runtime::kMath_sqrt, 1);
@ -3142,7 +3153,8 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() >= 2); ASSERT(args->length() >= 2);
int arg_count = args->length() - 2; // 2 ~ receiver and function. int arg_count = args->length() - 2; // 2 ~ receiver and function.
@ -3161,8 +3173,9 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
RegExpConstructResultStub stub; RegExpConstructResultStub stub;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 3); ASSERT(args->length() == 3);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3172,7 +3185,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 3); ASSERT(args->length() == 3);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3269,9 +3283,9 @@ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
ASSERT_NE(NULL, args->at(0)->AsLiteral()); ASSERT_NE(NULL, args->at(0)->AsLiteral());
int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
@ -3320,7 +3334,8 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
Register right = r0; Register right = r0;
@ -3360,7 +3375,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false; Label materialize_true, materialize_false;
@ -3372,14 +3388,15 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
__ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
__ tst(r0, Operand(String::kContainsCachedArrayIndexMask)); __ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -3394,12 +3411,12 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
Label bailout, done, one_char_separator, long_separator, Label bailout, done, one_char_separator, long_separator,
non_trivial_array, not_size_one_array, loop, non_trivial_array, not_size_one_array, loop,
empty_separator_loop, one_char_separator_loop, empty_separator_loop, one_char_separator_loop,
one_char_separator_loop_entry, long_separator_loop; one_char_separator_loop_entry, long_separator_loop;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -3727,18 +3744,35 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// Unary NOT has no side effects so it's only necessary to visit the // Unary NOT has no side effects so it's only necessary to visit the
// subexpression. Match the optimizing compiler by not branching. // subexpression. Match the optimizing compiler by not branching.
VisitForEffect(expr->expression()); VisitForEffect(expr->expression());
} else if (context()->IsTest()) {
const TestContext* test = TestContext::cast(context());
// The labels are swapped for the recursive call.
VisitForControl(expr->expression(),
test->false_label(),
test->true_label(),
test->fall_through());
context()->Plug(test->true_label(), test->false_label());
} else { } else {
Label materialize_true, materialize_false; // We handle value contexts explicitly rather than simply visiting
Label* if_true = NULL; // for control and plugging the control flow into the context,
Label* if_false = NULL; // because we need to prepare a pair of extra administrative AST ids
Label* fall_through = NULL; // for the optimizing compiler.
ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
// Notice that the labels are swapped. Label materialize_true, materialize_false, done;
context()->PrepareTest(&materialize_true, &materialize_false, VisitForControl(expr->expression(),
&if_false, &if_true, &fall_through); &materialize_false,
if (context()->IsTest()) ForwardBailoutToChild(expr); &materialize_true,
VisitForControl(expr->expression(), if_true, if_false, fall_through); &materialize_true);
context()->Plug(if_false, if_true); // Labels swapped. __ bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
__ LoadRoot(r0, Heap::kTrueValueRootIndex);
if (context()->IsStackValue()) __ push(r0);
__ jmp(&done);
__ bind(&materialize_false);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
__ LoadRoot(r0, Heap::kFalseValueRootIndex);
if (context()->IsStackValue()) __ push(r0);
__ bind(&done);
} }
break; break;
} }
@ -3997,12 +4031,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
context()->Plug(r0); context()->Plug(r0);
} else { } else {
// This expression cannot throw a reference error at the top level. // This expression cannot throw a reference error at the top level.
VisitInCurrentContext(expr); VisitInDuplicateContext(expr);
} }
} }
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
Expression* sub_expr,
Handle<String> check) { Handle<String> check) {
Label materialize_true, materialize_false; Label materialize_true, materialize_false;
Label* if_true = NULL; Label* if_true = NULL;
@ -4012,9 +4047,9 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
{ AccumulatorValueContext context(this); { AccumulatorValueContext context(this);
VisitForTypeofValue(expr); VisitForTypeofValue(sub_expr);
} }
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
if (check->Equals(isolate()->heap()->number_symbol())) { if (check->Equals(isolate()->heap()->number_symbol())) {
__ JumpIfSmi(r0, if_true); __ JumpIfSmi(r0, if_true);
@ -4101,7 +4136,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
case Token::IN: case Token::IN:
VisitForStackValue(expr->right()); VisitForStackValue(expr->right());
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
__ LoadRoot(ip, Heap::kTrueValueRootIndex); __ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(r0, ip); __ cmp(r0, ip);
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
@ -4111,7 +4146,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
VisitForStackValue(expr->right()); VisitForStackValue(expr->right());
InstanceofStub stub(InstanceofStub::kNoFlags); InstanceofStub stub(InstanceofStub::kNoFlags);
__ CallStub(&stub); __ CallStub(&stub);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
// The stub returns 0 for true. // The stub returns 0 for true.
__ tst(r0, r0); __ tst(r0, r0);
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
@ -4161,7 +4196,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
Handle<Code> ic = CompareIC::GetUninitialized(op); Handle<Code> ic = CompareIC::GetUninitialized(op);
__ Call(ic, RelocInfo::CODE_TARGET, expr->id()); __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
patch_site.EmitPatchInfo(); patch_site.EmitPatchInfo();
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ cmp(r0, Operand(0)); __ cmp(r0, Operand(0));
Split(cond, if_true, if_false, fall_through); Split(cond, if_true, if_false, fall_through);
} }
@ -4184,7 +4219,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
VisitForAccumulatorValue(sub_expr); VisitForAccumulatorValue(sub_expr);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Heap::RootListIndex nil_value = nil == kNullValue ? Heap::RootListIndex nil_value = nil == kNullValue ?
Heap::kNullValueRootIndex : Heap::kNullValueRootIndex :
Heap::kUndefinedValueRootIndex; Heap::kUndefinedValueRootIndex;

View File

@ -1288,8 +1288,17 @@ class UnaryOperation: public Expression {
Token::Value op, Token::Value op,
Expression* expression, Expression* expression,
int pos) int pos)
: Expression(isolate), op_(op), expression_(expression), pos_(pos) { : Expression(isolate),
op_(op),
expression_(expression),
pos_(pos),
materialize_true_id_(AstNode::kNoNumber),
materialize_false_id_(AstNode::kNoNumber) {
ASSERT(Token::IsUnaryOp(op)); ASSERT(Token::IsUnaryOp(op));
if (op == Token::NOT) {
materialize_true_id_ = GetNextId(isolate);
materialize_false_id_ = GetNextId(isolate);
}
} }
DECLARE_NODE_TYPE(UnaryOperation) DECLARE_NODE_TYPE(UnaryOperation)
@ -1302,10 +1311,18 @@ class UnaryOperation: public Expression {
Expression* expression() const { return expression_; } Expression* expression() const { return expression_; }
virtual int position() const { return pos_; } virtual int position() const { return pos_; }
int MaterializeTrueId() { return materialize_true_id_; }
int MaterializeFalseId() { return materialize_false_id_; }
private: private:
Token::Value op_; Token::Value op_;
Expression* expression_; Expression* expression_;
int pos_; int pos_;
// For unary not (Token::NOT), the AST ids where true and false will
// actually be materialized, respectively.
int materialize_true_id_;
int materialize_false_id_;
}; };

View File

@ -416,7 +416,7 @@ void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
void FullCodeGenerator::TestContext::Plug(Register reg) const { void FullCodeGenerator::TestContext::Plug(Register reg) const {
// For simplicity we always test the accumulator register. // For simplicity we always test the accumulator register.
__ Move(result_register(), reg); __ Move(result_register(), reg);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -438,7 +438,7 @@ void FullCodeGenerator::StackValueContext::PlugTOS() const {
void FullCodeGenerator::TestContext::PlugTOS() const { void FullCodeGenerator::TestContext::PlugTOS() const {
// For simplicity we always test the accumulator register. // For simplicity we always test the accumulator register.
__ pop(result_register()); __ pop(result_register());
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -652,14 +652,13 @@ FullCodeGenerator::InlineFunctionGenerator
} }
void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) { void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
ZoneList<Expression*>* args = node->arguments(); const Runtime::Function* function = expr->function();
const Runtime::Function* function = node->function();
ASSERT(function != NULL); ASSERT(function != NULL);
ASSERT(function->intrinsic_type == Runtime::INLINE); ASSERT(function->intrinsic_type == Runtime::INLINE);
InlineFunctionGenerator generator = InlineFunctionGenerator generator =
FindInlineFunctionGenerator(function->function_id); FindInlineFunctionGenerator(function->function_id);
((*this).*(generator))(args); ((*this).*(generator))(expr);
} }
@ -676,11 +675,25 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
} }
void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
if (context()->IsEffect()) {
VisitForEffect(expr);
} else if (context()->IsAccumulatorValue()) {
VisitForAccumulatorValue(expr);
} else if (context()->IsStackValue()) {
VisitForStackValue(expr);
} else if (context()->IsTest()) {
const TestContext* test = TestContext::cast(context());
VisitForControl(expr, test->true_label(), test->false_label(),
test->fall_through());
}
}
void FullCodeGenerator::VisitComma(BinaryOperation* expr) { void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
Comment cmnt(masm_, "[ Comma"); Comment cmnt(masm_, "[ Comma");
VisitForEffect(expr->left()); VisitForEffect(expr->left());
if (context()->IsTest()) ForwardBailoutToChild(expr); VisitInDuplicateContext(expr->right());
VisitInCurrentContext(expr->right());
} }
@ -702,7 +715,6 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
} }
PrepareForBailoutForId(right_id, NO_REGISTERS); PrepareForBailoutForId(right_id, NO_REGISTERS);
__ bind(&eval_right); __ bind(&eval_right);
ForwardBailoutToChild(expr);
} else if (context()->IsAccumulatorValue()) { } else if (context()->IsAccumulatorValue()) {
VisitForAccumulatorValue(left); VisitForAccumulatorValue(left);
@ -710,7 +722,6 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
// case we need it. // case we need it.
__ push(result_register()); __ push(result_register());
Label discard, restore; Label discard, restore;
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
if (is_logical_and) { if (is_logical_and) {
DoTest(left, &discard, &restore, &restore); DoTest(left, &discard, &restore, &restore);
} else { } else {
@ -729,7 +740,6 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
// case we need it. // case we need it.
__ push(result_register()); __ push(result_register());
Label discard; Label discard;
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
if (is_logical_and) { if (is_logical_and) {
DoTest(left, &discard, &done, &discard); DoTest(left, &discard, &done, &discard);
} else { } else {
@ -751,7 +761,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
__ bind(&eval_right); __ bind(&eval_right);
} }
VisitInCurrentContext(right); VisitInDuplicateContext(right);
__ bind(&done); __ bind(&done);
} }
@ -778,34 +788,6 @@ void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
} }
void FullCodeGenerator::ForwardBailoutToChild(Expression* expr) {
if (!info_->HasDeoptimizationSupport()) return;
ASSERT(context()->IsTest());
ASSERT(expr == forward_bailout_stack_->expr());
forward_bailout_pending_ = forward_bailout_stack_;
}
void FullCodeGenerator::VisitInCurrentContext(Expression* expr) {
if (context()->IsTest()) {
ForwardBailoutStack stack(expr, forward_bailout_pending_);
ForwardBailoutStack* saved = forward_bailout_stack_;
forward_bailout_pending_ = NULL;
forward_bailout_stack_ = &stack;
Visit(expr);
forward_bailout_stack_ = saved;
} else {
ASSERT(forward_bailout_pending_ == NULL);
Visit(expr);
State state = context()->IsAccumulatorValue() ? TOS_REG : NO_REGISTERS;
PrepareForBailout(expr, state);
// Forwarding bailouts to children is a one shot operation. It should have
// been processed at this point.
ASSERT(forward_bailout_pending_ == NULL);
}
}
void FullCodeGenerator::VisitBlock(Block* stmt) { void FullCodeGenerator::VisitBlock(Block* stmt) {
Comment cmnt(masm_, "[ Block"); Comment cmnt(masm_, "[ Block");
NestedBlock nested_block(this, stmt); NestedBlock nested_block(this, stmt);
@ -1247,16 +1229,15 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
for_test->false_label(), for_test->false_label(),
NULL); NULL);
} else { } else {
VisitInCurrentContext(expr->then_expression()); VisitInDuplicateContext(expr->then_expression());
__ jmp(&done); __ jmp(&done);
} }
PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
__ bind(&false_case); __ bind(&false_case);
if (context()->IsTest()) ForwardBailoutToChild(expr);
SetExpressionPosition(expr->else_expression(), SetExpressionPosition(expr->else_expression(),
expr->else_expression_position()); expr->else_expression_position());
VisitInCurrentContext(expr->else_expression()); VisitInDuplicateContext(expr->else_expression());
// If control flow falls through Visit, merge it with true case here. // If control flow falls through Visit, merge it with true case here.
if (!context()->IsTest()) { if (!context()->IsTest()) {
__ bind(&done); __ bind(&done);
@ -1314,7 +1295,7 @@ bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
Expression *sub_expr; Expression *sub_expr;
Handle<String> check; Handle<String> check;
if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
EmitLiteralCompareTypeof(sub_expr, check); EmitLiteralCompareTypeof(expr, sub_expr, check);
return true; return true;
} }

View File

@ -85,9 +85,7 @@ class FullCodeGenerator: public AstVisitor {
loop_depth_(0), loop_depth_(0),
context_(NULL), context_(NULL),
bailout_entries_(0), bailout_entries_(0),
stack_checks_(2), // There's always at least one. stack_checks_(2) { // There's always at least one.
forward_bailout_stack_(NULL),
forward_bailout_pending_(NULL) {
} }
static bool MakeCode(CompilationInfo* info); static bool MakeCode(CompilationInfo* info);
@ -275,27 +273,8 @@ class FullCodeGenerator: public AstVisitor {
} }
}; };
// The forward bailout stack keeps track of the expressions that can
// bail out to just before the control flow is split in a child
// node. The stack elements are linked together through the parent
// link when visiting expressions in test contexts after requesting
// bailout in child forwarding.
class ForwardBailoutStack BASE_EMBEDDED {
public:
ForwardBailoutStack(Expression* expr, ForwardBailoutStack* parent)
: expr_(expr), parent_(parent) { }
Expression* expr() const { return expr_; }
ForwardBailoutStack* parent() const { return parent_; }
private:
Expression* const expr_;
ForwardBailoutStack* const parent_;
};
// Type of a member function that generates inline code for a native function. // Type of a member function that generates inline code for a native function.
typedef void (FullCodeGenerator::*InlineFunctionGenerator) typedef void (FullCodeGenerator::*InlineFunctionGenerator)(CallRuntime* expr);
(ZoneList<Expression*>*);
static const InlineFunctionGenerator kInlineFunctionGenerators[]; static const InlineFunctionGenerator kInlineFunctionGenerators[];
@ -356,23 +335,22 @@ class FullCodeGenerator: public AstVisitor {
// need the write barrier if location is CONTEXT. // need the write barrier if location is CONTEXT.
MemOperand VarOperand(Variable* var, Register scratch); MemOperand VarOperand(Variable* var, Register scratch);
// Forward the bailout responsibility for the given expression to
// the next child visited (which must be in a test context).
void ForwardBailoutToChild(Expression* expr);
void VisitForEffect(Expression* expr) { void VisitForEffect(Expression* expr) {
EffectContext context(this); EffectContext context(this);
VisitInCurrentContext(expr); Visit(expr);
PrepareForBailout(expr, NO_REGISTERS);
} }
void VisitForAccumulatorValue(Expression* expr) { void VisitForAccumulatorValue(Expression* expr) {
AccumulatorValueContext context(this); AccumulatorValueContext context(this);
VisitInCurrentContext(expr); Visit(expr);
PrepareForBailout(expr, TOS_REG);
} }
void VisitForStackValue(Expression* expr) { void VisitForStackValue(Expression* expr) {
StackValueContext context(this); StackValueContext context(this);
VisitInCurrentContext(expr); Visit(expr);
PrepareForBailout(expr, NO_REGISTERS);
} }
void VisitForControl(Expression* expr, void VisitForControl(Expression* expr,
@ -380,9 +358,14 @@ class FullCodeGenerator: public AstVisitor {
Label* if_false, Label* if_false,
Label* fall_through) { Label* fall_through) {
TestContext context(this, expr, if_true, if_false, fall_through); TestContext context(this, expr, if_true, if_false, fall_through);
VisitInCurrentContext(expr); Visit(expr);
// For test contexts, we prepare for bailout before branching, not at
// the end of the entire expression. This happens as part of visiting
// the expression.
} }
void VisitInDuplicateContext(Expression* expr);
void VisitDeclarations(ZoneList<Declaration*>* declarations); void VisitDeclarations(ZoneList<Declaration*>* declarations);
void DeclareGlobals(Handle<FixedArray> pairs); void DeclareGlobals(Handle<FixedArray> pairs);
int DeclareGlobalsFlags(); int DeclareGlobalsFlags();
@ -394,7 +377,9 @@ class FullCodeGenerator: public AstVisitor {
// Platform-specific code for comparing the type of a value with // Platform-specific code for comparing the type of a value with
// a given literal string. // a given literal string.
void EmitLiteralCompareTypeof(Expression* expr, Handle<String> check); void EmitLiteralCompareTypeof(Expression* expr,
Expression* sub_expr,
Handle<String> check);
// Platform-specific code for equality comparison with a nil-like value. // Platform-specific code for equality comparison with a nil-like value.
void EmitLiteralCompareNil(CompareOperation* expr, void EmitLiteralCompareNil(CompareOperation* expr,
@ -414,7 +399,7 @@ class FullCodeGenerator: public AstVisitor {
// canonical JS true value so we will insert a (dead) test against true at // canonical JS true value so we will insert a (dead) test against true at
// the actual bailout target from the optimized code. If not // the actual bailout target from the optimized code. If not
// should_normalize, the true and false labels are ignored. // should_normalize, the true and false labels are ignored.
void PrepareForBailoutBeforeSplit(State state, void PrepareForBailoutBeforeSplit(Expression* expr,
bool should_normalize, bool should_normalize,
Label* if_true, Label* if_true,
Label* if_false); Label* if_false);
@ -449,7 +434,7 @@ class FullCodeGenerator: public AstVisitor {
void EmitInlineRuntimeCall(CallRuntime* expr); void EmitInlineRuntimeCall(CallRuntime* expr);
#define EMIT_INLINE_RUNTIME_CALL(name, x, y) \ #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
void Emit##name(ZoneList<Expression*>* arguments); void Emit##name(CallRuntime* expr);
INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
#undef EMIT_INLINE_RUNTIME_CALL #undef EMIT_INLINE_RUNTIME_CALL
@ -576,7 +561,6 @@ class FullCodeGenerator: public AstVisitor {
void VisitComma(BinaryOperation* expr); void VisitComma(BinaryOperation* expr);
void VisitLogicalExpression(BinaryOperation* expr); void VisitLogicalExpression(BinaryOperation* expr);
void VisitArithmeticExpression(BinaryOperation* expr); void VisitArithmeticExpression(BinaryOperation* expr);
void VisitInCurrentContext(Expression* expr);
void VisitForTypeofValue(Expression* expr); void VisitForTypeofValue(Expression* expr);
@ -771,8 +755,6 @@ class FullCodeGenerator: public AstVisitor {
const ExpressionContext* context_; const ExpressionContext* context_;
ZoneList<BailoutEntry> bailout_entries_; ZoneList<BailoutEntry> bailout_entries_;
ZoneList<BailoutEntry> stack_checks_; ZoneList<BailoutEntry> stack_checks_;
ForwardBailoutStack* forward_bailout_stack_;
ForwardBailoutStack* forward_bailout_pending_;
friend class NestedStatement; friend class NestedStatement;

View File

@ -5379,7 +5379,7 @@ void HGraphBuilder::VisitNot(UnaryOperation* expr) {
materialize_true)); materialize_true));
if (materialize_false->HasPredecessor()) { if (materialize_false->HasPredecessor()) {
materialize_false->SetJoinId(expr->expression()->id()); materialize_false->SetJoinId(expr->MaterializeFalseId());
set_current_block(materialize_false); set_current_block(materialize_false);
Push(graph()->GetConstantFalse()); Push(graph()->GetConstantFalse());
} else { } else {
@ -5387,7 +5387,7 @@ void HGraphBuilder::VisitNot(UnaryOperation* expr) {
} }
if (materialize_true->HasPredecessor()) { if (materialize_true->HasPredecessor()) {
materialize_true->SetJoinId(expr->expression()->id()); materialize_true->SetJoinId(expr->MaterializeTrueId());
set_current_block(materialize_true); set_current_block(materialize_true);
Push(graph()->GetConstantTrue()); Push(graph()->GetConstantTrue());
} else { } else {

View File

@ -384,7 +384,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
void FullCodeGenerator::TestContext::Plug(Variable* var) const { void FullCodeGenerator::TestContext::Plug(Variable* var) const {
// For simplicity we always test the accumulator register. // For simplicity we always test the accumulator register.
codegen()->GetVar(result_register(), var); codegen()->GetVar(result_register(), var);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -435,7 +435,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, codegen()->PrepareForBailoutBeforeSplit(condition(),
true, true,
true_label_, true_label_,
false_label_); false_label_);
@ -494,7 +494,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
// For simplicity we always test the accumulator register. // For simplicity we always test the accumulator register.
__ Drop(count); __ Drop(count);
__ Move(result_register(), reg); __ Move(result_register(), reg);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -560,7 +560,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
void FullCodeGenerator::TestContext::Plug(bool flag) const { void FullCodeGenerator::TestContext::Plug(bool flag) const {
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, codegen()->PrepareForBailoutBeforeSplit(condition(),
true, true,
true_label_, true_label_,
false_label_); false_label_);
@ -653,7 +653,7 @@ void FullCodeGenerator::SetVar(Variable* var,
} }
void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
bool should_normalize, bool should_normalize,
Label* if_true, Label* if_true,
Label* if_false) { Label* if_false) {
@ -664,13 +664,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
Label skip; Label skip;
if (should_normalize) __ jmp(&skip, Label::kNear); if (should_normalize) __ jmp(&skip, Label::kNear);
PrepareForBailout(expr, TOS_REG);
ForwardBailoutStack* current = forward_bailout_stack_;
while (current != NULL) {
PrepareForBailout(current->expr(), state);
current = current->parent();
}
if (should_normalize) { if (should_normalize) {
__ cmp(eax, isolate()->factory()->true_value()); __ cmp(eax, isolate()->factory()->true_value());
Split(equal, if_true, if_false, NULL); Split(equal, if_true, if_false, NULL);
@ -2270,7 +2264,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
} }
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2282,7 +2277,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false, context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ test(eax, Immediate(kSmiTagMask)); __ test(eax, Immediate(kSmiTagMask));
Split(zero, if_true, if_false, fall_through); Split(zero, if_true, if_false, fall_through);
@ -2290,7 +2285,8 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2302,7 +2298,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false, context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ test(eax, Immediate(kSmiTagMask | 0x80000000)); __ test(eax, Immediate(kSmiTagMask | 0x80000000));
Split(zero, if_true, if_false, fall_through); Split(zero, if_true, if_false, fall_through);
@ -2310,7 +2306,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2334,14 +2331,15 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
__ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
__ j(below, if_false); __ j(below, if_false);
__ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(below_equal, if_true, if_false, fall_through); Split(below_equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2355,14 +2353,15 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
__ JumpIfSmi(eax, if_false); __ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx); __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(above_equal, if_true, if_false, fall_through); Split(above_equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2378,7 +2377,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
__ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
__ test(ebx, Immediate(1 << Map::kIsUndetectable)); __ test(ebx, Immediate(1 << Map::kIsUndetectable));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(not_zero, if_true, if_false, fall_through); Split(not_zero, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -2386,7 +2385,8 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
ZoneList<Expression*>* args) { CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2463,12 +2463,13 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
__ jmp(if_true); __ jmp(if_true);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2482,14 +2483,15 @@ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
__ JumpIfSmi(eax, if_false); __ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2503,14 +2505,15 @@ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
__ JumpIfSmi(eax, if_false); __ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2524,7 +2527,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
__ JumpIfSmi(eax, if_false); __ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -2532,8 +2535,8 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
ASSERT(args->length() == 0); ASSERT(expr->arguments()->length() == 0);
Label materialize_true, materialize_false; Label materialize_true, materialize_false;
Label* if_true = NULL; Label* if_true = NULL;
@ -2556,14 +2559,15 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
__ bind(&check_frame_marker); __ bind(&check_frame_marker);
__ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset), __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
// Load the two objects into registers and perform the comparison. // Load the two objects into registers and perform the comparison.
@ -2579,14 +2583,15 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
__ pop(ebx); __ pop(ebx);
__ cmp(eax, ebx); __ cmp(eax, ebx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
// ArgumentsAccessStub expects the key in edx and the formal // ArgumentsAccessStub expects the key in edx and the formal
@ -2600,8 +2605,8 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
ASSERT(args->length() == 0); ASSERT(expr->arguments()->length() == 0);
Label exit; Label exit;
// Get the number of formal parameters. // Get the number of formal parameters.
@ -2623,7 +2628,8 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
Label done, null, function, non_function_constructor; Label done, null, function, non_function_constructor;
@ -2683,7 +2689,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitLog(CallRuntime* expr) {
// Conditionally generate a log call. // Conditionally generate a log call.
// Args: // Args:
// 0 (literal string): The type of logging (corresponds to the flags). // 0 (literal string): The type of logging (corresponds to the flags).
@ -2691,6 +2697,7 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
// 1 (string): Format string. Access the string at argument index 2 // 1 (string): Format string. Access the string at argument index 2
// with '%2s' (see Logger::LogRuntime for all the formats). // with '%2s' (see Logger::LogRuntime for all the formats).
// 2 (array): Arguments to the format string. // 2 (array): Arguments to the format string.
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(args->length(), 3); ASSERT_EQ(args->length(), 3);
if (CodeGenerator::ShouldGenerateLog(args->at(0))) { if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2703,8 +2710,8 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
ASSERT(args->length() == 0); ASSERT(expr->arguments()->length() == 0);
Label slow_allocate_heapnumber; Label slow_allocate_heapnumber;
Label heapnumber_allocated; Label heapnumber_allocated;
@ -2754,9 +2761,10 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
// Load the arguments on the stack and call the stub. // Load the arguments on the stack and call the stub.
SubStringStub stub; SubStringStub stub;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 3); ASSERT(args->length() == 3);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2766,9 +2774,10 @@ void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
// Load the arguments on the stack and call the stub. // Load the arguments on the stack and call the stub.
RegExpExecStub stub; RegExpExecStub stub;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 4); ASSERT(args->length() == 4);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2779,7 +2788,8 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); // Load the object. VisitForAccumulatorValue(args->at(0)); // Load the object.
@ -2797,8 +2807,9 @@ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
// Load the arguments on the stack and call the runtime function. // Load the arguments on the stack and call the runtime function.
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2813,7 +2824,8 @@ void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); // Load the object. VisitForStackValue(args->at(0)); // Load the object.
@ -2841,7 +2853,8 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(args->length(), 1); ASSERT_EQ(args->length(), 1);
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
@ -2853,7 +2866,8 @@ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2871,7 +2885,8 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
@ -2918,7 +2933,8 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
@ -2967,7 +2983,8 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
@ -2979,7 +2996,8 @@ void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
@ -2991,10 +3009,11 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::SIN, TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::TAGGED); TranscendentalCacheStub::TAGGED);
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -3002,10 +3021,11 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::COS, TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::TAGGED); TranscendentalCacheStub::TAGGED);
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -3013,10 +3033,11 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::LOG, TranscendentalCacheStub stub(TranscendentalCache::LOG,
TranscendentalCacheStub::TAGGED); TranscendentalCacheStub::TAGGED);
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -3024,8 +3045,9 @@ void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
// Load the argument on the stack and call the runtime function. // Load the argument on the stack and call the runtime function.
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallRuntime(Runtime::kMath_sqrt, 1); __ CallRuntime(Runtime::kMath_sqrt, 1);
@ -3033,7 +3055,8 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() >= 2); ASSERT(args->length() >= 2);
int arg_count = args->length() - 2; // 2 ~ receiver and function. int arg_count = args->length() - 2; // 2 ~ receiver and function.
@ -3052,9 +3075,10 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
// Load the arguments on the stack and call the stub. // Load the arguments on the stack and call the stub.
RegExpConstructResultStub stub; RegExpConstructResultStub stub;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 3); ASSERT(args->length() == 3);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3064,7 +3088,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 3); ASSERT(args->length() == 3);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3156,7 +3181,8 @@ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
ASSERT_NE(NULL, args->at(0)->AsLiteral()); ASSERT_NE(NULL, args->at(0)->AsLiteral());
@ -3204,7 +3230,8 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
Register right = eax; Register right = eax;
@ -3241,7 +3268,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -3259,14 +3287,15 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
__ test(FieldOperand(eax, String::kHashFieldOffset), __ test(FieldOperand(eax, String::kHashFieldOffset),
Immediate(String::kContainsCachedArrayIndexMask)); Immediate(String::kContainsCachedArrayIndexMask));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(zero, if_true, if_false, fall_through); Split(zero, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -3281,11 +3310,12 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
Label bailout, done, one_char_separator, long_separator, Label bailout, done, one_char_separator, long_separator,
non_trivial_array, not_size_one_array, loop, non_trivial_array, not_size_one_array, loop,
loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
// We will leave the separator on the stack until the end of the function. // We will leave the separator on the stack until the end of the function.
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3643,18 +3673,41 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// Unary NOT has no side effects so it's only necessary to visit the // Unary NOT has no side effects so it's only necessary to visit the
// subexpression. Match the optimizing compiler by not branching. // subexpression. Match the optimizing compiler by not branching.
VisitForEffect(expr->expression()); VisitForEffect(expr->expression());
} else if (context()->IsTest()) {
const TestContext* test = TestContext::cast(context());
// The labels are swapped for the recursive call.
VisitForControl(expr->expression(),
test->false_label(),
test->true_label(),
test->fall_through());
context()->Plug(test->true_label(), test->false_label());
} else { } else {
Label materialize_true, materialize_false; // We handle value contexts explicitly rather than simply visiting
Label* if_true = NULL; // for control and plugging the control flow into the context,
Label* if_false = NULL; // because we need to prepare a pair of extra administrative AST ids
Label* fall_through = NULL; // for the optimizing compiler.
ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
// Notice that the labels are swapped. Label materialize_true, materialize_false, done;
context()->PrepareTest(&materialize_true, &materialize_false, VisitForControl(expr->expression(),
&if_false, &if_true, &fall_through); &materialize_false,
if (context()->IsTest()) ForwardBailoutToChild(expr); &materialize_true,
VisitForControl(expr->expression(), if_true, if_false, fall_through); &materialize_true);
context()->Plug(if_false, if_true); // Labels swapped. __ bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ mov(eax, isolate()->factory()->true_value());
} else {
__ push(isolate()->factory()->true_value());
}
__ jmp(&done, Label::kNear);
__ bind(&materialize_false);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ mov(eax, isolate()->factory()->false_value());
} else {
__ push(isolate()->factory()->false_value());
}
__ bind(&done);
} }
break; break;
} }
@ -3925,12 +3978,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
context()->Plug(eax); context()->Plug(eax);
} else { } else {
// This expression cannot throw a reference error at the top level. // This expression cannot throw a reference error at the top level.
VisitInCurrentContext(expr); VisitInDuplicateContext(expr);
} }
} }
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
Expression* sub_expr,
Handle<String> check) { Handle<String> check) {
Label materialize_true, materialize_false; Label materialize_true, materialize_false;
Label* if_true = NULL; Label* if_true = NULL;
@ -3940,9 +3994,9 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
{ AccumulatorValueContext context(this); { AccumulatorValueContext context(this);
VisitForTypeofValue(expr); VisitForTypeofValue(sub_expr);
} }
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
if (check->Equals(isolate()->heap()->number_symbol())) { if (check->Equals(isolate()->heap()->number_symbol())) {
__ JumpIfSmi(eax, if_true); __ JumpIfSmi(eax, if_true);
@ -4026,7 +4080,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
case Token::IN: case Token::IN:
VisitForStackValue(expr->right()); VisitForStackValue(expr->right());
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
__ cmp(eax, isolate()->factory()->true_value()); __ cmp(eax, isolate()->factory()->true_value());
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
break; break;
@ -4035,7 +4089,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
VisitForStackValue(expr->right()); VisitForStackValue(expr->right());
InstanceofStub stub(InstanceofStub::kNoFlags); InstanceofStub stub(InstanceofStub::kNoFlags);
__ CallStub(&stub); __ CallStub(&stub);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ test(eax, eax); __ test(eax, eax);
// The stub returns 0 for true. // The stub returns 0 for true.
Split(zero, if_true, if_false, fall_through); Split(zero, if_true, if_false, fall_through);
@ -4087,7 +4141,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
__ call(ic, RelocInfo::CODE_TARGET, expr->id()); __ call(ic, RelocInfo::CODE_TARGET, expr->id());
patch_site.EmitPatchInfo(); patch_site.EmitPatchInfo();
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ test(eax, eax); __ test(eax, eax);
Split(cc, if_true, if_false, fall_through); Split(cc, if_true, if_false, fall_through);
} }
@ -4110,7 +4164,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
VisitForAccumulatorValue(sub_expr); VisitForAccumulatorValue(sub_expr);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Handle<Object> nil_value = nil == kNullValue ? Handle<Object> nil_value = nil == kNullValue ?
isolate()->factory()->null_value() : isolate()->factory()->null_value() :
isolate()->factory()->undefined_value(); isolate()->factory()->undefined_value();

View File

@ -405,7 +405,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
void FullCodeGenerator::TestContext::Plug(Variable* var) const { void FullCodeGenerator::TestContext::Plug(Variable* var) const {
// For simplicity we always test the accumulator register. // For simplicity we always test the accumulator register.
codegen()->GetVar(result_register(), var); codegen()->GetVar(result_register(), var);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -522,7 +522,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
// For simplicity we always test the accumulator register. // For simplicity we always test the accumulator register.
__ Drop(count); __ Drop(count);
__ Move(result_register(), reg); __ Move(result_register(), reg);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -2413,7 +2413,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false, context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
__ And(t0, v0, Operand(kSmiTagMask)); __ And(t0, v0, Operand(kSmiTagMask));
Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through); Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through);
@ -2433,7 +2433,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false, context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
__ And(at, v0, Operand(kSmiTagMask | 0x80000000)); __ And(at, v0, Operand(kSmiTagMask | 0x80000000));
Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through); Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through);
@ -2463,7 +2463,7 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
__ Branch(if_false, ne, at, Operand(zero_reg)); __ Branch(if_false, ne, at, Operand(zero_reg));
__ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset)); __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
__ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE), Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE),
if_true, if_false, fall_through); if_true, if_false, fall_through);
@ -2485,7 +2485,7 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
__ JumpIfSmi(v0, if_false); __ JumpIfSmi(v0, if_false);
__ GetObjectType(v0, a1, a1); __ GetObjectType(v0, a1, a1);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE), Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE),
if_true, if_false, fall_through); if_true, if_false, fall_through);
@ -2509,7 +2509,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
__ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
__ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset)); __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset));
__ And(at, a1, Operand(1 << Map::kIsUndetectable)); __ And(at, a1, Operand(1 << Map::kIsUndetectable));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through); Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -2594,7 +2594,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
__ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset)); __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset));
__ jmp(if_true); __ jmp(if_true);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
@ -2613,7 +2613,7 @@ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
__ JumpIfSmi(v0, if_false); __ JumpIfSmi(v0, if_false);
__ GetObjectType(v0, a1, a2); __ GetObjectType(v0, a1, a2);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
__ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE)); __ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE));
__ Branch(if_false); __ Branch(if_false);
@ -2635,7 +2635,7 @@ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
__ JumpIfSmi(v0, if_false); __ JumpIfSmi(v0, if_false);
__ GetObjectType(v0, a1, a1); __ GetObjectType(v0, a1, a1);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Split(eq, a1, Operand(JS_ARRAY_TYPE), Split(eq, a1, Operand(JS_ARRAY_TYPE),
if_true, if_false, fall_through); if_true, if_false, fall_through);
@ -2657,7 +2657,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
__ JumpIfSmi(v0, if_false); __ JumpIfSmi(v0, if_false);
__ GetObjectType(v0, a1, a1); __ GetObjectType(v0, a1, a1);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through); Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -2687,7 +2687,7 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
// Check the marker in the calling frame. // Check the marker in the calling frame.
__ bind(&check_frame_marker); __ bind(&check_frame_marker);
__ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset)); __ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)), Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)),
if_true, if_false, fall_through); if_true, if_false, fall_through);
@ -2710,7 +2710,7 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
__ pop(a1); __ pop(a1);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Split(eq, v0, Operand(a1), if_true, if_false, fall_through); Split(eq, v0, Operand(a1), if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -3396,7 +3396,7 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
__ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset)); __ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset));
__ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask)); __ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through); Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -4048,7 +4048,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
{ AccumulatorValueContext context(this); { AccumulatorValueContext context(this);
VisitForTypeofValue(expr); VisitForTypeofValue(expr);
} }
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
if (check->Equals(isolate()->heap()->number_symbol())) { if (check->Equals(isolate()->heap()->number_symbol())) {
__ JumpIfSmi(v0, if_true); __ JumpIfSmi(v0, if_true);
@ -4134,7 +4134,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
case Token::IN: case Token::IN:
VisitForStackValue(expr->right()); VisitForStackValue(expr->right());
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); PrepareForBailoutBeforeSplit(false, NULL, NULL);
__ LoadRoot(t0, Heap::kTrueValueRootIndex); __ LoadRoot(t0, Heap::kTrueValueRootIndex);
Split(eq, v0, Operand(t0), if_true, if_false, fall_through); Split(eq, v0, Operand(t0), if_true, if_false, fall_through);
break; break;
@ -4143,7 +4143,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
VisitForStackValue(expr->right()); VisitForStackValue(expr->right());
InstanceofStub stub(InstanceofStub::kNoFlags); InstanceofStub stub(InstanceofStub::kNoFlags);
__ CallStub(&stub); __ CallStub(&stub);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
// The stub returns 0 for true. // The stub returns 0 for true.
Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through); Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through);
break; break;
@ -4191,7 +4191,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
Handle<Code> ic = CompareIC::GetUninitialized(op); Handle<Code> ic = CompareIC::GetUninitialized(op);
__ Call(ic, RelocInfo::CODE_TARGET, expr->id()); __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
patch_site.EmitPatchInfo(); patch_site.EmitPatchInfo();
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
} }
} }
@ -4213,7 +4213,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
VisitForAccumulatorValue(sub_expr); VisitForAccumulatorValue(sub_expr);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(true, if_true, if_false);
Heap::RootListIndex nil_value = nil == kNullValue ? Heap::RootListIndex nil_value = nil == kNullValue ?
Heap::kNullValueRootIndex : Heap::kNullValueRootIndex :
Heap::kUndefinedValueRootIndex; Heap::kUndefinedValueRootIndex;

View File

@ -378,7 +378,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
void FullCodeGenerator::TestContext::Plug(Variable* var) const { void FullCodeGenerator::TestContext::Plug(Variable* var) const {
codegen()->GetVar(result_register(), var); codegen()->GetVar(result_register(), var);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -400,7 +400,7 @@ void FullCodeGenerator::StackValueContext::Plug(
void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, codegen()->PrepareForBailoutBeforeSplit(condition(),
true, true,
true_label_, true_label_,
false_label_); false_label_);
@ -433,7 +433,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, codegen()->PrepareForBailoutBeforeSplit(condition(),
true, true,
true_label_, true_label_,
false_label_); false_label_);
@ -492,7 +492,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
// For simplicity we always test the accumulator register. // For simplicity we always test the accumulator register.
__ Drop(count); __ Drop(count);
__ Move(result_register(), reg); __ Move(result_register(), reg);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this); codegen()->DoTest(this);
} }
@ -556,7 +556,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
void FullCodeGenerator::TestContext::Plug(bool flag) const { void FullCodeGenerator::TestContext::Plug(bool flag) const {
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, codegen()->PrepareForBailoutBeforeSplit(condition(),
true, true,
true_label_, true_label_,
false_label_); false_label_);
@ -648,7 +648,7 @@ void FullCodeGenerator::SetVar(Variable* var,
} }
void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
bool should_normalize, bool should_normalize,
Label* if_true, Label* if_true,
Label* if_false) { Label* if_false) {
@ -659,13 +659,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
Label skip; Label skip;
if (should_normalize) __ jmp(&skip, Label::kNear); if (should_normalize) __ jmp(&skip, Label::kNear);
PrepareForBailout(expr, TOS_REG);
ForwardBailoutStack* current = forward_bailout_stack_;
while (current != NULL) {
PrepareForBailout(current->expr(), state);
current = current->parent();
}
if (should_normalize) { if (should_normalize) {
__ CompareRoot(rax, Heap::kTrueValueRootIndex); __ CompareRoot(rax, Heap::kTrueValueRootIndex);
Split(equal, if_true, if_false, NULL); Split(equal, if_true, if_false, NULL);
@ -2264,7 +2258,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
} }
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2276,7 +2271,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false, context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ JumpIfSmi(rax, if_true); __ JumpIfSmi(rax, if_true);
__ jmp(if_false); __ jmp(if_false);
@ -2284,7 +2279,8 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2296,7 +2292,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false, context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
Split(non_negative_smi, if_true, if_false, fall_through); Split(non_negative_smi, if_true, if_false, fall_through);
@ -2304,7 +2300,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2328,14 +2325,15 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
__ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ j(below, if_false); __ j(below, if_false);
__ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); __ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(below_equal, if_true, if_false, fall_through); Split(below_equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2349,14 +2347,15 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
__ JumpIfSmi(rax, if_false); __ JumpIfSmi(rax, if_false);
__ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx); __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(above_equal, if_true, if_false, fall_through); Split(above_equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2372,7 +2371,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
__ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
__ testb(FieldOperand(rbx, Map::kBitFieldOffset), __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable)); Immediate(1 << Map::kIsUndetectable));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(not_zero, if_true, if_false, fall_through); Split(not_zero, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -2380,7 +2379,8 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
ZoneList<Expression*>* args) { CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2456,12 +2456,13 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
__ jmp(if_true); __ jmp(if_true);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2475,14 +2476,15 @@ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
__ JumpIfSmi(rax, if_false); __ JumpIfSmi(rax, if_false);
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2496,14 +2498,15 @@ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
__ JumpIfSmi(rax, if_false); __ JumpIfSmi(rax, if_false);
__ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2517,7 +2520,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
__ JumpIfSmi(rax, if_false); __ JumpIfSmi(rax, if_false);
__ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
@ -2525,8 +2528,8 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
ASSERT(args->length() == 0); ASSERT(expr->arguments()->length() == 0);
Label materialize_true, materialize_false; Label materialize_true, materialize_false;
Label* if_true = NULL; Label* if_true = NULL;
@ -2549,14 +2552,15 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
__ bind(&check_frame_marker); __ bind(&check_frame_marker);
__ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset), __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
Smi::FromInt(StackFrame::CONSTRUCT)); Smi::FromInt(StackFrame::CONSTRUCT));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
// Load the two objects into registers and perform the comparison. // Load the two objects into registers and perform the comparison.
@ -2572,14 +2576,15 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
__ pop(rbx); __ pop(rbx);
__ cmpq(rax, rbx); __ cmpq(rax, rbx);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
// ArgumentsAccessStub expects the key in rdx and the formal // ArgumentsAccessStub expects the key in rdx and the formal
@ -2593,8 +2598,8 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
ASSERT(args->length() == 0); ASSERT(expr->arguments()->length() == 0);
Label exit; Label exit;
// Get the number of formal parameters. // Get the number of formal parameters.
@ -2616,7 +2621,8 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
Label done, null, function, non_function_constructor; Label done, null, function, non_function_constructor;
@ -2676,7 +2682,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitLog(CallRuntime* expr) {
// Conditionally generate a log call. // Conditionally generate a log call.
// Args: // Args:
// 0 (literal string): The type of logging (corresponds to the flags). // 0 (literal string): The type of logging (corresponds to the flags).
@ -2684,6 +2690,7 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
// 1 (string): Format string. Access the string at argument index 2 // 1 (string): Format string. Access the string at argument index 2
// with '%2s' (see Logger::LogRuntime for all the formats). // with '%2s' (see Logger::LogRuntime for all the formats).
// 2 (array): Arguments to the format string. // 2 (array): Arguments to the format string.
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(args->length(), 3); ASSERT_EQ(args->length(), 3);
if (CodeGenerator::ShouldGenerateLog(args->at(0))) { if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2696,8 +2703,8 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
ASSERT(args->length() == 0); ASSERT(expr->arguments()->length() == 0);
Label slow_allocate_heapnumber; Label slow_allocate_heapnumber;
Label heapnumber_allocated; Label heapnumber_allocated;
@ -2741,9 +2748,10 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
// Load the arguments on the stack and call the stub. // Load the arguments on the stack and call the stub.
SubStringStub stub; SubStringStub stub;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 3); ASSERT(args->length() == 3);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2753,9 +2761,10 @@ void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
// Load the arguments on the stack and call the stub. // Load the arguments on the stack and call the stub.
RegExpExecStub stub; RegExpExecStub stub;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 4); ASSERT(args->length() == 4);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2766,7 +2775,8 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); // Load the object. VisitForAccumulatorValue(args->at(0)); // Load the object.
@ -2784,8 +2794,9 @@ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
// Load the arguments on the stack and call the runtime function. // Load the arguments on the stack and call the runtime function.
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -2795,7 +2806,8 @@ void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); // Load the object. VisitForStackValue(args->at(0)); // Load the object.
@ -2822,7 +2834,8 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(args->length(), 1); ASSERT_EQ(args->length(), 1);
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
@ -2834,7 +2847,8 @@ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -2852,7 +2866,8 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
@ -2899,7 +2914,8 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
@ -2948,7 +2964,8 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
@ -2960,7 +2977,8 @@ void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
@ -2972,10 +2990,11 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::SIN, TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::TAGGED); TranscendentalCacheStub::TAGGED);
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -2983,10 +3002,11 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::COS, TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::TAGGED); TranscendentalCacheStub::TAGGED);
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -2994,10 +3014,11 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::LOG, TranscendentalCacheStub stub(TranscendentalCache::LOG,
TranscendentalCacheStub::TAGGED); TranscendentalCacheStub::TAGGED);
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -3005,8 +3026,9 @@ void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
// Load the argument on the stack and call the runtime function. // Load the argument on the stack and call the runtime function.
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallRuntime(Runtime::kMath_sqrt, 1); __ CallRuntime(Runtime::kMath_sqrt, 1);
@ -3014,7 +3036,8 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() >= 2); ASSERT(args->length() >= 2);
int arg_count = args->length() - 2; // 2 ~ receiver and function. int arg_count = args->length() - 2; // 2 ~ receiver and function.
@ -3033,8 +3056,9 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
RegExpConstructResultStub stub; RegExpConstructResultStub stub;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 3); ASSERT(args->length() == 3);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3044,7 +3068,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 3); ASSERT(args->length() == 3);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3139,7 +3164,8 @@ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
ASSERT_NE(NULL, args->at(0)->AsLiteral()); ASSERT_NE(NULL, args->at(0)->AsLiteral());
@ -3195,7 +3221,8 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length()); ASSERT_EQ(2, args->length());
Register right = rax; Register right = rax;
@ -3233,7 +3260,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -3247,7 +3275,7 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
__ testl(FieldOperand(rax, String::kHashFieldOffset), __ testl(FieldOperand(rax, String::kHashFieldOffset),
Immediate(String::kContainsCachedArrayIndexMask)); Immediate(String::kContainsCachedArrayIndexMask));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ j(zero, if_true); __ j(zero, if_true);
__ jmp(if_false); __ jmp(if_false);
@ -3255,7 +3283,8 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
@ -3271,10 +3300,11 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
} }
void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
Label bailout, return_result, done, one_char_separator, long_separator, Label bailout, return_result, done, one_char_separator, long_separator,
non_trivial_array, not_size_one_array, loop, non_trivial_array, not_size_one_array, loop,
loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
// We will leave the separator on the stack until the end of the function. // We will leave the separator on the stack until the end of the function.
VisitForStackValue(args->at(1)); VisitForStackValue(args->at(1));
@ -3653,17 +3683,41 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// Unary NOT has no side effects so it's only necessary to visit the // Unary NOT has no side effects so it's only necessary to visit the
// subexpression. Match the optimizing compiler by not branching. // subexpression. Match the optimizing compiler by not branching.
VisitForEffect(expr->expression()); VisitForEffect(expr->expression());
} else if (context()->IsTest()) {
const TestContext* test = TestContext::cast(context());
// The labels are swapped for the recursive call.
VisitForControl(expr->expression(),
test->false_label(),
test->true_label(),
test->fall_through());
context()->Plug(test->true_label(), test->false_label());
} else { } else {
Label materialize_true, materialize_false; // We handle value contexts explicitly rather than simply visiting
Label* if_true = NULL; // for control and plugging the control flow into the context,
Label* if_false = NULL; // because we need to prepare a pair of extra administrative AST ids
Label* fall_through = NULL; // for the optimizing compiler.
// Notice that the labels are swapped. ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
context()->PrepareTest(&materialize_true, &materialize_false, Label materialize_true, materialize_false, done;
&if_false, &if_true, &fall_through); VisitForControl(expr->expression(),
if (context()->IsTest()) ForwardBailoutToChild(expr); &materialize_false,
VisitForControl(expr->expression(), if_true, if_false, fall_through); &materialize_true,
context()->Plug(if_false, if_true); // Labels swapped. &materialize_true);
__ bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ LoadRoot(rax, Heap::kTrueValueRootIndex);
} else {
__ PushRoot(Heap::kTrueValueRootIndex);
}
__ jmp(&done, Label::kNear);
__ bind(&materialize_false);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ LoadRoot(rax, Heap::kFalseValueRootIndex);
} else {
__ PushRoot(Heap::kFalseValueRootIndex);
}
__ bind(&done);
} }
break; break;
} }
@ -3935,12 +3989,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
context()->Plug(rax); context()->Plug(rax);
} else { } else {
// This expression cannot throw a reference error at the top level. // This expression cannot throw a reference error at the top level.
VisitInCurrentContext(expr); VisitInDuplicateContext(expr);
} }
} }
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
Expression* sub_expr,
Handle<String> check) { Handle<String> check) {
Label materialize_true, materialize_false; Label materialize_true, materialize_false;
Label* if_true = NULL; Label* if_true = NULL;
@ -3950,9 +4005,9 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
{ AccumulatorValueContext context(this); { AccumulatorValueContext context(this);
VisitForTypeofValue(expr); VisitForTypeofValue(sub_expr);
} }
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
if (check->Equals(isolate()->heap()->number_symbol())) { if (check->Equals(isolate()->heap()->number_symbol())) {
__ JumpIfSmi(rax, if_true); __ JumpIfSmi(rax, if_true);
@ -4036,7 +4091,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
case Token::IN: case Token::IN:
VisitForStackValue(expr->right()); VisitForStackValue(expr->right());
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
__ CompareRoot(rax, Heap::kTrueValueRootIndex); __ CompareRoot(rax, Heap::kTrueValueRootIndex);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
break; break;
@ -4045,7 +4100,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
VisitForStackValue(expr->right()); VisitForStackValue(expr->right());
InstanceofStub stub(InstanceofStub::kNoFlags); InstanceofStub stub(InstanceofStub::kNoFlags);
__ CallStub(&stub); __ CallStub(&stub);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ testq(rax, rax); __ testq(rax, rax);
// The stub returns 0 for true. // The stub returns 0 for true.
Split(zero, if_true, if_false, fall_through); Split(zero, if_true, if_false, fall_through);
@ -4097,7 +4152,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
__ call(ic, RelocInfo::CODE_TARGET, expr->id()); __ call(ic, RelocInfo::CODE_TARGET, expr->id());
patch_site.EmitPatchInfo(); patch_site.EmitPatchInfo();
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ testq(rax, rax); __ testq(rax, rax);
Split(cc, if_true, if_false, fall_through); Split(cc, if_true, if_false, fall_through);
} }
@ -4120,7 +4175,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
&if_true, &if_false, &fall_through); &if_true, &if_false, &fall_through);
VisitForAccumulatorValue(sub_expr); VisitForAccumulatorValue(sub_expr);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Heap::RootListIndex nil_value = nil == kNullValue ? Heap::RootListIndex nil_value = nil == kNullValue ?
Heap::kNullValueRootIndex : Heap::kNullValueRootIndex :
Heap::kUndefinedValueRootIndex; Heap::kUndefinedValueRootIndex;