diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 3d75c143aa..d0c663b408 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -394,7 +394,7 @@ void FullCodeGenerator::TestContext::Plug(Variable* var) const { ASSERT(var->IsStackAllocated() || var->IsContextSlot()); // For simplicity we always test the accumulator register. codegen()->GetVar(result_register(), var); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); codegen()->DoTest(this); } @@ -417,7 +417,7 @@ void FullCodeGenerator::StackValueContext::Plug( void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, + codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, false_label_); @@ -452,7 +452,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle lit) const { void FullCodeGenerator::TestContext::Plug(Handle lit) const { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, + codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, false_label_); @@ -511,7 +511,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count, // For simplicity we always test the accumulator register. __ Drop(count); __ Move(result_register(), reg); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); codegen()->DoTest(this); } @@ -578,7 +578,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const { void FullCodeGenerator::TestContext::Plug(bool flag) const { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, + codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_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, Label* if_true, Label* if_false) { @@ -692,13 +692,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, Label skip; if (should_normalize) __ b(&skip); - - ForwardBailoutStack* current = forward_bailout_stack_; - while (current != NULL) { - PrepareForBailout(current->expr(), state); - current = current->parent(); - } - + PrepareForBailout(expr, TOS_REG); if (should_normalize) { __ LoadRoot(ip, Heap::kTrueValueRootIndex); __ cmp(r0, ip); @@ -2377,7 +2371,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { } -void FullCodeGenerator::EmitIsSmi(ZoneList* args) { +void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2389,7 +2384,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { context()->PrepareTest(&materialize_true, &materialize_false, &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)); Split(eq, if_true, if_false, fall_through); @@ -2397,7 +2392,8 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { } -void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { +void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2409,7 +2405,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { context()->PrepareTest(&materialize_true, &materialize_false, &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)); Split(eq, if_true, if_false, fall_through); @@ -2417,7 +2413,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { } -void FullCodeGenerator::EmitIsObject(ZoneList* args) { +void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2442,14 +2439,15 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); __ b(lt, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { +void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2463,14 +2461,15 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { __ JumpIfSmi(r0, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { +void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2486,7 +2485,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); __ 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); context()->Plug(if_true, if_false); @@ -2494,8 +2493,8 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( - ZoneList* args) { - + CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2574,12 +2573,13 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset)); __ jmp(if_true); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsFunction(ZoneList* args) { +void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2593,14 +2593,15 @@ void FullCodeGenerator::EmitIsFunction(ZoneList* args) { __ JumpIfSmi(r0, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsArray(ZoneList* args) { +void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2614,14 +2615,15 @@ void FullCodeGenerator::EmitIsArray(ZoneList* args) { __ JumpIfSmi(r0, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { +void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2635,7 +2637,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { __ JumpIfSmi(r0, if_false); __ 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); context()->Plug(if_true, if_false); @@ -2643,8 +2645,8 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { -void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { - ASSERT(args->length() == 0); +void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); Label materialize_true, materialize_false; Label* if_true = NULL; @@ -2667,14 +2669,15 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { __ bind(&check_frame_marker); __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { +void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); // Load the two objects into registers and perform the comparison. @@ -2690,14 +2693,15 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { __ pop(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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitArguments(ZoneList* args) { +void FullCodeGenerator::EmitArguments(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); // ArgumentsAccessStub expects the key in edx and the formal @@ -2711,9 +2715,8 @@ void FullCodeGenerator::EmitArguments(ZoneList* args) { } -void FullCodeGenerator::EmitArgumentsLength(ZoneList* args) { - ASSERT(args->length() == 0); - +void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); Label exit; // Get the number of formal parameters. __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); @@ -2733,7 +2736,8 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList* args) { } -void FullCodeGenerator::EmitClassOf(ZoneList* args) { +void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); Label done, null, function, non_function_constructor; @@ -2793,7 +2797,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList* args) { } -void FullCodeGenerator::EmitLog(ZoneList* args) { +void FullCodeGenerator::EmitLog(CallRuntime* expr) { // Conditionally generate a log call. // Args: // 0 (literal string): The type of logging (corresponds to the flags). @@ -2801,6 +2805,7 @@ void FullCodeGenerator::EmitLog(ZoneList* args) { // 1 (string): Format string. Access the string at argument index 2 // with '%2s' (see Logger::LogRuntime for all the formats). // 2 (array): Arguments to the format string. + ZoneList* args = expr->arguments(); ASSERT_EQ(args->length(), 3); if (CodeGenerator::ShouldGenerateLog(args->at(0))) { VisitForStackValue(args->at(1)); @@ -2814,9 +2819,8 @@ void FullCodeGenerator::EmitLog(ZoneList* args) { } -void FullCodeGenerator::EmitRandomHeapNumber(ZoneList* args) { - ASSERT(args->length() == 0); - +void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); Label slow_allocate_heapnumber; Label heapnumber_allocated; @@ -2868,9 +2872,10 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList* args) { } -void FullCodeGenerator::EmitSubString(ZoneList* args) { +void FullCodeGenerator::EmitSubString(CallRuntime* expr) { // Load the arguments on the stack and call the stub. SubStringStub stub; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -2880,9 +2885,10 @@ void FullCodeGenerator::EmitSubString(ZoneList* args) { } -void FullCodeGenerator::EmitRegExpExec(ZoneList* args) { +void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { // Load the arguments on the stack and call the stub. RegExpExecStub stub; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 4); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -2893,9 +2899,9 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList* args) { } -void FullCodeGenerator::EmitValueOf(ZoneList* args) { +void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); - VisitForAccumulatorValue(args->at(0)); // Load the object. Label done; @@ -2911,8 +2917,9 @@ void FullCodeGenerator::EmitValueOf(ZoneList* args) { } -void FullCodeGenerator::EmitMathPow(ZoneList* args) { +void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { // Load the arguments on the stack and call the runtime function. + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -2922,9 +2929,9 @@ void FullCodeGenerator::EmitMathPow(ZoneList* args) { } -void FullCodeGenerator::EmitSetValueOf(ZoneList* args) { +void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); - VisitForStackValue(args->at(0)); // Load the object. VisitForAccumulatorValue(args->at(1)); // Load the value. __ pop(r1); // r0 = value. r1 = object. @@ -2950,9 +2957,9 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList* args) { } -void FullCodeGenerator::EmitNumberToString(ZoneList* args) { +void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(args->length(), 1); - // Load the argument on the stack and call the stub. VisitForStackValue(args->at(0)); @@ -2962,9 +2969,9 @@ void FullCodeGenerator::EmitNumberToString(ZoneList* args) { } -void FullCodeGenerator::EmitStringCharFromCode(ZoneList* args) { +void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); - VisitForAccumulatorValue(args->at(0)); Label done; @@ -2980,9 +2987,9 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList* args) { } -void FullCodeGenerator::EmitStringCharCodeAt(ZoneList* args) { +void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); - VisitForStackValue(args->at(0)); VisitForAccumulatorValue(args->at(1)); @@ -3027,9 +3034,9 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList* args) { } -void FullCodeGenerator::EmitStringCharAt(ZoneList* args) { +void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); - VisitForStackValue(args->at(0)); VisitForAccumulatorValue(args->at(1)); @@ -3076,9 +3083,9 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList* args) { } -void FullCodeGenerator::EmitStringAdd(ZoneList* args) { +void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); - VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -3088,9 +3095,9 @@ void FullCodeGenerator::EmitStringAdd(ZoneList* args) { } -void FullCodeGenerator::EmitStringCompare(ZoneList* args) { +void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); - VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -3100,10 +3107,11 @@ void FullCodeGenerator::EmitStringCompare(ZoneList* args) { } -void FullCodeGenerator::EmitMathSin(ZoneList* args) { +void FullCodeGenerator::EmitMathSin(CallRuntime* expr) { // Load the argument on the stack and call the stub. TranscendentalCacheStub stub(TranscendentalCache::SIN, TranscendentalCacheStub::TAGGED); + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallStub(&stub); @@ -3111,10 +3119,11 @@ void FullCodeGenerator::EmitMathSin(ZoneList* args) { } -void FullCodeGenerator::EmitMathCos(ZoneList* args) { +void FullCodeGenerator::EmitMathCos(CallRuntime* expr) { // Load the argument on the stack and call the stub. TranscendentalCacheStub stub(TranscendentalCache::COS, TranscendentalCacheStub::TAGGED); + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallStub(&stub); @@ -3122,10 +3131,11 @@ void FullCodeGenerator::EmitMathCos(ZoneList* args) { } -void FullCodeGenerator::EmitMathLog(ZoneList* args) { +void FullCodeGenerator::EmitMathLog(CallRuntime* expr) { // Load the argument on the stack and call the stub. TranscendentalCacheStub stub(TranscendentalCache::LOG, TranscendentalCacheStub::TAGGED); + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallStub(&stub); @@ -3133,8 +3143,9 @@ void FullCodeGenerator::EmitMathLog(ZoneList* args) { } -void FullCodeGenerator::EmitMathSqrt(ZoneList* args) { +void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) { // Load the argument on the stack and call the runtime function. + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallRuntime(Runtime::kMath_sqrt, 1); @@ -3142,7 +3153,8 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList* args) { } -void FullCodeGenerator::EmitCallFunction(ZoneList* args) { +void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() >= 2); int arg_count = args->length() - 2; // 2 ~ receiver and function. @@ -3161,8 +3173,9 @@ void FullCodeGenerator::EmitCallFunction(ZoneList* args) { } -void FullCodeGenerator::EmitRegExpConstructResult(ZoneList* args) { +void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { RegExpConstructResultStub stub; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -3172,7 +3185,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList* args) { } -void FullCodeGenerator::EmitSwapElements(ZoneList* args) { +void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -3269,9 +3283,9 @@ void FullCodeGenerator::EmitSwapElements(ZoneList* args) { } -void FullCodeGenerator::EmitGetFromCache(ZoneList* args) { +void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); - ASSERT_NE(NULL, args->at(0)->AsLiteral()); int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); @@ -3320,7 +3334,8 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList* args) { } -void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList* args) { +void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); Register right = r0; @@ -3360,7 +3375,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList* args) { } -void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { +void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { + ZoneList* args = expr->arguments(); VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; @@ -3372,14 +3388,15 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList* args) { +void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3394,12 +3411,12 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList* args) { } -void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList* args) { +void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { Label bailout, done, one_char_separator, long_separator, non_trivial_array, not_size_one_array, loop, empty_separator_loop, one_char_separator_loop, one_char_separator_loop_entry, long_separator_loop; - + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(1)); 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 // subexpression. Match the optimizing compiler by not branching. 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 { - Label materialize_true, materialize_false; - Label* if_true = NULL; - Label* if_false = NULL; - Label* fall_through = NULL; - - // Notice that the labels are swapped. - context()->PrepareTest(&materialize_true, &materialize_false, - &if_false, &if_true, &fall_through); - if (context()->IsTest()) ForwardBailoutToChild(expr); - VisitForControl(expr->expression(), if_true, if_false, fall_through); - context()->Plug(if_false, if_true); // Labels swapped. + // We handle value contexts explicitly rather than simply visiting + // for control and plugging the control flow into the context, + // because we need to prepare a pair of extra administrative AST ids + // for the optimizing compiler. + ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); + Label materialize_true, materialize_false, done; + VisitForControl(expr->expression(), + &materialize_false, + &materialize_true, + &materialize_true); + __ 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; } @@ -3997,12 +4031,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { context()->Plug(r0); } else { // This expression cannot throw a reference error at the top level. - VisitInCurrentContext(expr); + VisitInDuplicateContext(expr); } } void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, + Expression* sub_expr, Handle check) { Label materialize_true, materialize_false; Label* if_true = NULL; @@ -4012,9 +4047,9 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, &if_true, &if_false, &fall_through); { 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())) { __ JumpIfSmi(r0, if_true); @@ -4101,7 +4136,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { case Token::IN: VisitForStackValue(expr->right()); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); - PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); __ LoadRoot(ip, Heap::kTrueValueRootIndex); __ cmp(r0, ip); Split(eq, if_true, if_false, fall_through); @@ -4111,7 +4146,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { VisitForStackValue(expr->right()); InstanceofStub stub(InstanceofStub::kNoFlags); __ CallStub(&stub); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); // The stub returns 0 for true. __ tst(r0, r0); Split(eq, if_true, if_false, fall_through); @@ -4161,7 +4196,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { Handle ic = CompareIC::GetUninitialized(op); __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); patch_site.EmitPatchInfo(); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); __ cmp(r0, Operand(0)); Split(cond, if_true, if_false, fall_through); } @@ -4184,7 +4219,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, &if_true, &if_false, &fall_through); 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::kNullValueRootIndex : Heap::kUndefinedValueRootIndex; diff --git a/src/ast.h b/src/ast.h index 13af3f3b1d..295257aaeb 100644 --- a/src/ast.h +++ b/src/ast.h @@ -1288,8 +1288,17 @@ class UnaryOperation: public Expression { Token::Value op, Expression* expression, 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)); + if (op == Token::NOT) { + materialize_true_id_ = GetNextId(isolate); + materialize_false_id_ = GetNextId(isolate); + } } DECLARE_NODE_TYPE(UnaryOperation) @@ -1302,10 +1311,18 @@ class UnaryOperation: public Expression { Expression* expression() const { return expression_; } virtual int position() const { return pos_; } + int MaterializeTrueId() { return materialize_true_id_; } + int MaterializeFalseId() { return materialize_false_id_; } + private: Token::Value op_; Expression* expression_; 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_; }; diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 6c798ac670..e6fac19323 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -416,7 +416,7 @@ void FullCodeGenerator::StackValueContext::Plug(Register reg) const { void FullCodeGenerator::TestContext::Plug(Register reg) const { // For simplicity we always test the accumulator register. __ Move(result_register(), reg); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); codegen()->DoTest(this); } @@ -438,7 +438,7 @@ void FullCodeGenerator::StackValueContext::PlugTOS() const { void FullCodeGenerator::TestContext::PlugTOS() const { // For simplicity we always test the accumulator register. __ pop(result_register()); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); codegen()->DoTest(this); } @@ -652,14 +652,13 @@ FullCodeGenerator::InlineFunctionGenerator } -void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) { - ZoneList* args = node->arguments(); - const Runtime::Function* function = node->function(); +void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { + const Runtime::Function* function = expr->function(); ASSERT(function != NULL); ASSERT(function->intrinsic_type == Runtime::INLINE); InlineFunctionGenerator generator = 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) { Comment cmnt(masm_, "[ Comma"); VisitForEffect(expr->left()); - if (context()->IsTest()) ForwardBailoutToChild(expr); - VisitInCurrentContext(expr->right()); + VisitInDuplicateContext(expr->right()); } @@ -702,7 +715,6 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) { } PrepareForBailoutForId(right_id, NO_REGISTERS); __ bind(&eval_right); - ForwardBailoutToChild(expr); } else if (context()->IsAccumulatorValue()) { VisitForAccumulatorValue(left); @@ -710,7 +722,6 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) { // case we need it. __ push(result_register()); Label discard, restore; - PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); if (is_logical_and) { DoTest(left, &discard, &restore, &restore); } else { @@ -729,7 +740,6 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) { // case we need it. __ push(result_register()); Label discard; - PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); if (is_logical_and) { DoTest(left, &discard, &done, &discard); } else { @@ -751,7 +761,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) { __ bind(&eval_right); } - VisitInCurrentContext(right); + VisitInDuplicateContext(right); __ 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) { Comment cmnt(masm_, "[ Block"); NestedBlock nested_block(this, stmt); @@ -1247,16 +1229,15 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) { for_test->false_label(), NULL); } else { - VisitInCurrentContext(expr->then_expression()); + VisitInDuplicateContext(expr->then_expression()); __ jmp(&done); } PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); __ bind(&false_case); - if (context()->IsTest()) ForwardBailoutToChild(expr); SetExpressionPosition(expr->else_expression(), 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 (!context()->IsTest()) { __ bind(&done); @@ -1314,7 +1295,7 @@ bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) { Expression *sub_expr; Handle check; if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { - EmitLiteralCompareTypeof(sub_expr, check); + EmitLiteralCompareTypeof(expr, sub_expr, check); return true; } diff --git a/src/full-codegen.h b/src/full-codegen.h index e5693ed4cf..799f96d088 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h @@ -85,9 +85,7 @@ class FullCodeGenerator: public AstVisitor { loop_depth_(0), context_(NULL), bailout_entries_(0), - stack_checks_(2), // There's always at least one. - forward_bailout_stack_(NULL), - forward_bailout_pending_(NULL) { + stack_checks_(2) { // There's always at least one. } 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. - typedef void (FullCodeGenerator::*InlineFunctionGenerator) - (ZoneList*); + typedef void (FullCodeGenerator::*InlineFunctionGenerator)(CallRuntime* expr); static const InlineFunctionGenerator kInlineFunctionGenerators[]; @@ -356,23 +335,22 @@ class FullCodeGenerator: public AstVisitor { // need the write barrier if location is CONTEXT. 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) { EffectContext context(this); - VisitInCurrentContext(expr); + Visit(expr); + PrepareForBailout(expr, NO_REGISTERS); } void VisitForAccumulatorValue(Expression* expr) { AccumulatorValueContext context(this); - VisitInCurrentContext(expr); + Visit(expr); + PrepareForBailout(expr, TOS_REG); } void VisitForStackValue(Expression* expr) { StackValueContext context(this); - VisitInCurrentContext(expr); + Visit(expr); + PrepareForBailout(expr, NO_REGISTERS); } void VisitForControl(Expression* expr, @@ -380,9 +358,14 @@ class FullCodeGenerator: public AstVisitor { Label* if_false, Label* 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* declarations); void DeclareGlobals(Handle pairs); int DeclareGlobalsFlags(); @@ -394,7 +377,9 @@ class FullCodeGenerator: public AstVisitor { // Platform-specific code for comparing the type of a value with // a given literal string. - void EmitLiteralCompareTypeof(Expression* expr, Handle check); + void EmitLiteralCompareTypeof(Expression* expr, + Expression* sub_expr, + Handle check); // Platform-specific code for equality comparison with a nil-like value. 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 // the actual bailout target from the optimized code. If not // should_normalize, the true and false labels are ignored. - void PrepareForBailoutBeforeSplit(State state, + void PrepareForBailoutBeforeSplit(Expression* expr, bool should_normalize, Label* if_true, Label* if_false); @@ -449,7 +434,7 @@ class FullCodeGenerator: public AstVisitor { void EmitInlineRuntimeCall(CallRuntime* expr); #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \ - void Emit##name(ZoneList* arguments); + void Emit##name(CallRuntime* expr); INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) #undef EMIT_INLINE_RUNTIME_CALL @@ -576,7 +561,6 @@ class FullCodeGenerator: public AstVisitor { void VisitComma(BinaryOperation* expr); void VisitLogicalExpression(BinaryOperation* expr); void VisitArithmeticExpression(BinaryOperation* expr); - void VisitInCurrentContext(Expression* expr); void VisitForTypeofValue(Expression* expr); @@ -771,8 +755,6 @@ class FullCodeGenerator: public AstVisitor { const ExpressionContext* context_; ZoneList bailout_entries_; ZoneList stack_checks_; - ForwardBailoutStack* forward_bailout_stack_; - ForwardBailoutStack* forward_bailout_pending_; friend class NestedStatement; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 90619c5941..a7a022d5ec 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -5379,7 +5379,7 @@ void HGraphBuilder::VisitNot(UnaryOperation* expr) { materialize_true)); if (materialize_false->HasPredecessor()) { - materialize_false->SetJoinId(expr->expression()->id()); + materialize_false->SetJoinId(expr->MaterializeFalseId()); set_current_block(materialize_false); Push(graph()->GetConstantFalse()); } else { @@ -5387,7 +5387,7 @@ void HGraphBuilder::VisitNot(UnaryOperation* expr) { } if (materialize_true->HasPredecessor()) { - materialize_true->SetJoinId(expr->expression()->id()); + materialize_true->SetJoinId(expr->MaterializeTrueId()); set_current_block(materialize_true); Push(graph()->GetConstantTrue()); } else { diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 0c59335d28..0af30f079f 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -384,7 +384,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { void FullCodeGenerator::TestContext::Plug(Variable* var) const { // For simplicity we always test the accumulator register. codegen()->GetVar(result_register(), var); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); codegen()->DoTest(this); } @@ -435,7 +435,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle lit) const { void FullCodeGenerator::TestContext::Plug(Handle lit) const { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, + codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, false_label_); @@ -494,7 +494,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count, // For simplicity we always test the accumulator register. __ Drop(count); __ Move(result_register(), reg); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); codegen()->DoTest(this); } @@ -560,7 +560,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const { void FullCodeGenerator::TestContext::Plug(bool flag) const { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, + codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_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, Label* if_true, Label* if_false) { @@ -664,13 +664,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, Label skip; if (should_normalize) __ jmp(&skip, Label::kNear); - - ForwardBailoutStack* current = forward_bailout_stack_; - while (current != NULL) { - PrepareForBailout(current->expr(), state); - current = current->parent(); - } - + PrepareForBailout(expr, TOS_REG); if (should_normalize) { __ cmp(eax, isolate()->factory()->true_value()); Split(equal, if_true, if_false, NULL); @@ -2270,7 +2264,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { } -void FullCodeGenerator::EmitIsSmi(ZoneList* args) { +void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2282,7 +2277,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { context()->PrepareTest(&materialize_true, &materialize_false, &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)); Split(zero, if_true, if_false, fall_through); @@ -2290,7 +2285,8 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { } -void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { +void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2302,7 +2298,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { context()->PrepareTest(&materialize_true, &materialize_false, &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)); Split(zero, if_true, if_false, fall_through); @@ -2310,7 +2306,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { } -void FullCodeGenerator::EmitIsObject(ZoneList* args) { +void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2334,14 +2331,15 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); __ j(below, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { +void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2355,14 +2353,15 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { __ JumpIfSmi(eax, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { +void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2378,7 +2377,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); __ 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); context()->Plug(if_true, if_false); @@ -2386,7 +2385,8 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( - ZoneList* args) { + CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2463,12 +2463,13 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); __ jmp(if_true); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsFunction(ZoneList* args) { +void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2482,14 +2483,15 @@ void FullCodeGenerator::EmitIsFunction(ZoneList* args) { __ JumpIfSmi(eax, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsArray(ZoneList* args) { +void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2503,14 +2505,15 @@ void FullCodeGenerator::EmitIsArray(ZoneList* args) { __ JumpIfSmi(eax, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { +void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2524,7 +2527,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { __ JumpIfSmi(eax, if_false); __ 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); context()->Plug(if_true, if_false); @@ -2532,8 +2535,8 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { -void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { - ASSERT(args->length() == 0); +void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); Label materialize_true, materialize_false; Label* if_true = NULL; @@ -2556,14 +2559,15 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { __ bind(&check_frame_marker); __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset), 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { +void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); // Load the two objects into registers and perform the comparison. @@ -2579,14 +2583,15 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { __ pop(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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitArguments(ZoneList* args) { +void FullCodeGenerator::EmitArguments(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); // ArgumentsAccessStub expects the key in edx and the formal @@ -2600,8 +2605,8 @@ void FullCodeGenerator::EmitArguments(ZoneList* args) { } -void FullCodeGenerator::EmitArgumentsLength(ZoneList* args) { - ASSERT(args->length() == 0); +void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); Label exit; // Get the number of formal parameters. @@ -2623,7 +2628,8 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList* args) { } -void FullCodeGenerator::EmitClassOf(ZoneList* args) { +void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); Label done, null, function, non_function_constructor; @@ -2683,7 +2689,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList* args) { } -void FullCodeGenerator::EmitLog(ZoneList* args) { +void FullCodeGenerator::EmitLog(CallRuntime* expr) { // Conditionally generate a log call. // Args: // 0 (literal string): The type of logging (corresponds to the flags). @@ -2691,6 +2697,7 @@ void FullCodeGenerator::EmitLog(ZoneList* args) { // 1 (string): Format string. Access the string at argument index 2 // with '%2s' (see Logger::LogRuntime for all the formats). // 2 (array): Arguments to the format string. + ZoneList* args = expr->arguments(); ASSERT_EQ(args->length(), 3); if (CodeGenerator::ShouldGenerateLog(args->at(0))) { VisitForStackValue(args->at(1)); @@ -2703,8 +2710,8 @@ void FullCodeGenerator::EmitLog(ZoneList* args) { } -void FullCodeGenerator::EmitRandomHeapNumber(ZoneList* args) { - ASSERT(args->length() == 0); +void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); Label slow_allocate_heapnumber; Label heapnumber_allocated; @@ -2754,9 +2761,10 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList* args) { } -void FullCodeGenerator::EmitSubString(ZoneList* args) { +void FullCodeGenerator::EmitSubString(CallRuntime* expr) { // Load the arguments on the stack and call the stub. SubStringStub stub; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -2766,9 +2774,10 @@ void FullCodeGenerator::EmitSubString(ZoneList* args) { } -void FullCodeGenerator::EmitRegExpExec(ZoneList* args) { +void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { // Load the arguments on the stack and call the stub. RegExpExecStub stub; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 4); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -2779,7 +2788,8 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList* args) { } -void FullCodeGenerator::EmitValueOf(ZoneList* args) { +void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); // Load the object. @@ -2797,8 +2807,9 @@ void FullCodeGenerator::EmitValueOf(ZoneList* args) { } -void FullCodeGenerator::EmitMathPow(ZoneList* args) { +void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { // Load the arguments on the stack and call the runtime function. + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -2813,7 +2824,8 @@ void FullCodeGenerator::EmitMathPow(ZoneList* args) { } -void FullCodeGenerator::EmitSetValueOf(ZoneList* args) { +void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(0)); // Load the object. @@ -2841,7 +2853,8 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList* args) { } -void FullCodeGenerator::EmitNumberToString(ZoneList* args) { +void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(args->length(), 1); // Load the argument on the stack and call the stub. @@ -2853,7 +2866,8 @@ void FullCodeGenerator::EmitNumberToString(ZoneList* args) { } -void FullCodeGenerator::EmitStringCharFromCode(ZoneList* args) { +void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2871,7 +2885,8 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList* args) { } -void FullCodeGenerator::EmitStringCharCodeAt(ZoneList* args) { +void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(0)); @@ -2918,7 +2933,8 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList* args) { } -void FullCodeGenerator::EmitStringCharAt(ZoneList* args) { +void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(0)); @@ -2967,7 +2983,8 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList* args) { } -void FullCodeGenerator::EmitStringAdd(ZoneList* args) { +void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); VisitForStackValue(args->at(0)); @@ -2979,7 +2996,8 @@ void FullCodeGenerator::EmitStringAdd(ZoneList* args) { } -void FullCodeGenerator::EmitStringCompare(ZoneList* args) { +void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); VisitForStackValue(args->at(0)); @@ -2991,10 +3009,11 @@ void FullCodeGenerator::EmitStringCompare(ZoneList* args) { } -void FullCodeGenerator::EmitMathSin(ZoneList* args) { +void FullCodeGenerator::EmitMathSin(CallRuntime* expr) { // Load the argument on the stack and call the stub. TranscendentalCacheStub stub(TranscendentalCache::SIN, TranscendentalCacheStub::TAGGED); + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallStub(&stub); @@ -3002,10 +3021,11 @@ void FullCodeGenerator::EmitMathSin(ZoneList* args) { } -void FullCodeGenerator::EmitMathCos(ZoneList* args) { +void FullCodeGenerator::EmitMathCos(CallRuntime* expr) { // Load the argument on the stack and call the stub. TranscendentalCacheStub stub(TranscendentalCache::COS, TranscendentalCacheStub::TAGGED); + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallStub(&stub); @@ -3013,10 +3033,11 @@ void FullCodeGenerator::EmitMathCos(ZoneList* args) { } -void FullCodeGenerator::EmitMathLog(ZoneList* args) { +void FullCodeGenerator::EmitMathLog(CallRuntime* expr) { // Load the argument on the stack and call the stub. TranscendentalCacheStub stub(TranscendentalCache::LOG, TranscendentalCacheStub::TAGGED); + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallStub(&stub); @@ -3024,8 +3045,9 @@ void FullCodeGenerator::EmitMathLog(ZoneList* args) { } -void FullCodeGenerator::EmitMathSqrt(ZoneList* args) { +void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) { // Load the argument on the stack and call the runtime function. + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallRuntime(Runtime::kMath_sqrt, 1); @@ -3033,7 +3055,8 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList* args) { } -void FullCodeGenerator::EmitCallFunction(ZoneList* args) { +void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() >= 2); int arg_count = args->length() - 2; // 2 ~ receiver and function. @@ -3052,9 +3075,10 @@ void FullCodeGenerator::EmitCallFunction(ZoneList* args) { } -void FullCodeGenerator::EmitRegExpConstructResult(ZoneList* args) { +void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { // Load the arguments on the stack and call the stub. RegExpConstructResultStub stub; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -3064,7 +3088,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList* args) { } -void FullCodeGenerator::EmitSwapElements(ZoneList* args) { +void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -3156,7 +3181,8 @@ void FullCodeGenerator::EmitSwapElements(ZoneList* args) { } -void FullCodeGenerator::EmitGetFromCache(ZoneList* args) { +void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); ASSERT_NE(NULL, args->at(0)->AsLiteral()); @@ -3204,7 +3230,8 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList* args) { } -void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList* args) { +void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); Register right = eax; @@ -3241,7 +3268,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList* args) { } -void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { +void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3259,14 +3287,15 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { __ test(FieldOperand(eax, String::kHashFieldOffset), 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList* args) { +void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3281,11 +3310,12 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList* args) { } -void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList* args) { +void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { Label bailout, done, one_char_separator, long_separator, non_trivial_array, not_size_one_array, loop, loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); // We will leave the separator on the stack until the end of the function. 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 // subexpression. Match the optimizing compiler by not branching. 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 { - Label materialize_true, materialize_false; - Label* if_true = NULL; - Label* if_false = NULL; - Label* fall_through = NULL; - - // Notice that the labels are swapped. - context()->PrepareTest(&materialize_true, &materialize_false, - &if_false, &if_true, &fall_through); - if (context()->IsTest()) ForwardBailoutToChild(expr); - VisitForControl(expr->expression(), if_true, if_false, fall_through); - context()->Plug(if_false, if_true); // Labels swapped. + // We handle value contexts explicitly rather than simply visiting + // for control and plugging the control flow into the context, + // because we need to prepare a pair of extra administrative AST ids + // for the optimizing compiler. + ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); + Label materialize_true, materialize_false, done; + VisitForControl(expr->expression(), + &materialize_false, + &materialize_true, + &materialize_true); + __ 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; } @@ -3925,12 +3978,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { context()->Plug(eax); } else { // This expression cannot throw a reference error at the top level. - VisitInCurrentContext(expr); + VisitInDuplicateContext(expr); } } void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, + Expression* sub_expr, Handle check) { Label materialize_true, materialize_false; Label* if_true = NULL; @@ -3940,9 +3994,9 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, &if_true, &if_false, &fall_through); { 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())) { __ JumpIfSmi(eax, if_true); @@ -4026,7 +4080,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { case Token::IN: VisitForStackValue(expr->right()); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); - PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); __ cmp(eax, isolate()->factory()->true_value()); Split(equal, if_true, if_false, fall_through); break; @@ -4035,7 +4089,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { VisitForStackValue(expr->right()); InstanceofStub stub(InstanceofStub::kNoFlags); __ CallStub(&stub); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); __ test(eax, eax); // The stub returns 0 for true. Split(zero, if_true, if_false, fall_through); @@ -4087,7 +4141,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { __ call(ic, RelocInfo::CODE_TARGET, expr->id()); patch_site.EmitPatchInfo(); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); __ test(eax, eax); Split(cc, if_true, if_false, fall_through); } @@ -4110,7 +4164,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, &if_true, &if_false, &fall_through); VisitForAccumulatorValue(sub_expr); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); Handle nil_value = nil == kNullValue ? isolate()->factory()->null_value() : isolate()->factory()->undefined_value(); diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index 07d1c06780..09c9b8e918 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -405,7 +405,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { void FullCodeGenerator::TestContext::Plug(Variable* var) const { // For simplicity we always test the accumulator register. codegen()->GetVar(result_register(), var); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL); codegen()->DoTest(this); } @@ -522,7 +522,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count, // For simplicity we always test the accumulator register. __ Drop(count); __ Move(result_register(), reg); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL); codegen()->DoTest(this); } @@ -2413,7 +2413,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { context()->PrepareTest(&materialize_true, &materialize_false, &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)); Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through); @@ -2433,7 +2433,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { context()->PrepareTest(&materialize_true, &materialize_false, &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)); Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through); @@ -2463,7 +2463,7 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { __ Branch(if_false, ne, at, Operand(zero_reg)); __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset)); __ 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), if_true, if_false, fall_through); @@ -2485,7 +2485,7 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { __ JumpIfSmi(v0, if_false); __ 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), if_true, if_false, fall_through); @@ -2509,7 +2509,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset)); __ 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); context()->Plug(if_true, if_false); @@ -2594,7 +2594,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset)); __ jmp(if_true); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(true, if_true, if_false); context()->Plug(if_true, if_false); } @@ -2613,7 +2613,7 @@ void FullCodeGenerator::EmitIsFunction(ZoneList* args) { __ JumpIfSmi(v0, if_false); __ 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_false); @@ -2635,7 +2635,7 @@ void FullCodeGenerator::EmitIsArray(ZoneList* args) { __ JumpIfSmi(v0, if_false); __ 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), if_true, if_false, fall_through); @@ -2657,7 +2657,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { __ JumpIfSmi(v0, if_false); __ 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); context()->Plug(if_true, if_false); @@ -2687,7 +2687,7 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { // Check the marker in the calling frame. __ bind(&check_frame_marker); __ 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)), if_true, if_false, fall_through); @@ -2710,7 +2710,7 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { &if_true, &if_false, &fall_through); __ 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); context()->Plug(if_true, if_false); @@ -3396,7 +3396,7 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { __ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset)); __ 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); context()->Plug(if_true, if_false); @@ -4048,7 +4048,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, { AccumulatorValueContext context(this); VisitForTypeofValue(expr); } - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(true, if_true, if_false); if (check->Equals(isolate()->heap()->number_symbol())) { __ JumpIfSmi(v0, if_true); @@ -4134,7 +4134,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { case Token::IN: VisitForStackValue(expr->right()); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); - PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + PrepareForBailoutBeforeSplit(false, NULL, NULL); __ LoadRoot(t0, Heap::kTrueValueRootIndex); Split(eq, v0, Operand(t0), if_true, if_false, fall_through); break; @@ -4143,7 +4143,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { VisitForStackValue(expr->right()); InstanceofStub stub(InstanceofStub::kNoFlags); __ CallStub(&stub); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(true, if_true, if_false); // The stub returns 0 for true. Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through); break; @@ -4191,7 +4191,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { Handle ic = CompareIC::GetUninitialized(op); __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); 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); } } @@ -4213,7 +4213,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, &if_true, &if_false, &fall_through); VisitForAccumulatorValue(sub_expr); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(true, if_true, if_false); Heap::RootListIndex nil_value = nil == kNullValue ? Heap::kNullValueRootIndex : Heap::kUndefinedValueRootIndex; diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 831a7df0ef..e8fdef21f9 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -378,7 +378,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { void FullCodeGenerator::TestContext::Plug(Variable* var) const { codegen()->GetVar(result_register(), var); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); codegen()->DoTest(this); } @@ -400,7 +400,7 @@ void FullCodeGenerator::StackValueContext::Plug( void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, + codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, false_label_); @@ -433,7 +433,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle lit) const { void FullCodeGenerator::TestContext::Plug(Handle lit) const { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, + codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, false_label_); @@ -492,7 +492,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count, // For simplicity we always test the accumulator register. __ Drop(count); __ Move(result_register(), reg); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); codegen()->DoTest(this); } @@ -556,7 +556,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const { void FullCodeGenerator::TestContext::Plug(bool flag) const { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, + codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_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, Label* if_true, Label* if_false) { @@ -659,13 +659,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, Label skip; if (should_normalize) __ jmp(&skip, Label::kNear); - - ForwardBailoutStack* current = forward_bailout_stack_; - while (current != NULL) { - PrepareForBailout(current->expr(), state); - current = current->parent(); - } - + PrepareForBailout(expr, TOS_REG); if (should_normalize) { __ CompareRoot(rax, Heap::kTrueValueRootIndex); Split(equal, if_true, if_false, NULL); @@ -2264,7 +2258,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { } -void FullCodeGenerator::EmitIsSmi(ZoneList* args) { +void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2276,7 +2271,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { context()->PrepareTest(&materialize_true, &materialize_false, &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); __ jmp(if_false); @@ -2284,7 +2279,8 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { } -void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { +void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2296,7 +2292,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { context()->PrepareTest(&materialize_true, &materialize_false, &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); Split(non_negative_smi, if_true, if_false, fall_through); @@ -2304,7 +2300,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { } -void FullCodeGenerator::EmitIsObject(ZoneList* args) { +void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2328,14 +2325,15 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); __ j(below, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { +void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2349,14 +2347,15 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { __ JumpIfSmi(rax, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { +void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2372,7 +2371,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 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); context()->Plug(if_true, if_false); @@ -2380,7 +2379,8 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( - ZoneList* args) { + CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2456,12 +2456,13 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); __ jmp(if_true); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsFunction(ZoneList* args) { +void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2475,14 +2476,15 @@ void FullCodeGenerator::EmitIsFunction(ZoneList* args) { __ JumpIfSmi(rax, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsArray(ZoneList* args) { +void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2496,14 +2498,15 @@ void FullCodeGenerator::EmitIsArray(ZoneList* args) { __ JumpIfSmi(rax, if_false); __ 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { +void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2517,7 +2520,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { __ JumpIfSmi(rax, if_false); __ 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); context()->Plug(if_true, if_false); @@ -2525,8 +2528,8 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { -void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { - ASSERT(args->length() == 0); +void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); Label materialize_true, materialize_false; Label* if_true = NULL; @@ -2549,14 +2552,15 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { __ bind(&check_frame_marker); __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset), 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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { +void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); // Load the two objects into registers and perform the comparison. @@ -2572,14 +2576,15 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { __ pop(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); context()->Plug(if_true, if_false); } -void FullCodeGenerator::EmitArguments(ZoneList* args) { +void FullCodeGenerator::EmitArguments(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); // ArgumentsAccessStub expects the key in rdx and the formal @@ -2593,8 +2598,8 @@ void FullCodeGenerator::EmitArguments(ZoneList* args) { } -void FullCodeGenerator::EmitArgumentsLength(ZoneList* args) { - ASSERT(args->length() == 0); +void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); Label exit; // Get the number of formal parameters. @@ -2616,7 +2621,8 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList* args) { } -void FullCodeGenerator::EmitClassOf(ZoneList* args) { +void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); Label done, null, function, non_function_constructor; @@ -2676,7 +2682,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList* args) { } -void FullCodeGenerator::EmitLog(ZoneList* args) { +void FullCodeGenerator::EmitLog(CallRuntime* expr) { // Conditionally generate a log call. // Args: // 0 (literal string): The type of logging (corresponds to the flags). @@ -2684,6 +2690,7 @@ void FullCodeGenerator::EmitLog(ZoneList* args) { // 1 (string): Format string. Access the string at argument index 2 // with '%2s' (see Logger::LogRuntime for all the formats). // 2 (array): Arguments to the format string. + ZoneList* args = expr->arguments(); ASSERT_EQ(args->length(), 3); if (CodeGenerator::ShouldGenerateLog(args->at(0))) { VisitForStackValue(args->at(1)); @@ -2696,8 +2703,8 @@ void FullCodeGenerator::EmitLog(ZoneList* args) { } -void FullCodeGenerator::EmitRandomHeapNumber(ZoneList* args) { - ASSERT(args->length() == 0); +void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); Label slow_allocate_heapnumber; Label heapnumber_allocated; @@ -2741,9 +2748,10 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList* args) { } -void FullCodeGenerator::EmitSubString(ZoneList* args) { +void FullCodeGenerator::EmitSubString(CallRuntime* expr) { // Load the arguments on the stack and call the stub. SubStringStub stub; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -2753,9 +2761,10 @@ void FullCodeGenerator::EmitSubString(ZoneList* args) { } -void FullCodeGenerator::EmitRegExpExec(ZoneList* args) { +void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { // Load the arguments on the stack and call the stub. RegExpExecStub stub; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 4); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -2766,7 +2775,8 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList* args) { } -void FullCodeGenerator::EmitValueOf(ZoneList* args) { +void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); // Load the object. @@ -2784,8 +2794,9 @@ void FullCodeGenerator::EmitValueOf(ZoneList* args) { } -void FullCodeGenerator::EmitMathPow(ZoneList* args) { +void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { // Load the arguments on the stack and call the runtime function. + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -2795,7 +2806,8 @@ void FullCodeGenerator::EmitMathPow(ZoneList* args) { } -void FullCodeGenerator::EmitSetValueOf(ZoneList* args) { +void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(0)); // Load the object. @@ -2822,7 +2834,8 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList* args) { } -void FullCodeGenerator::EmitNumberToString(ZoneList* args) { +void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(args->length(), 1); // Load the argument on the stack and call the stub. @@ -2834,7 +2847,8 @@ void FullCodeGenerator::EmitNumberToString(ZoneList* args) { } -void FullCodeGenerator::EmitStringCharFromCode(ZoneList* args) { +void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2852,7 +2866,8 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList* args) { } -void FullCodeGenerator::EmitStringCharCodeAt(ZoneList* args) { +void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(0)); @@ -2899,7 +2914,8 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList* args) { } -void FullCodeGenerator::EmitStringCharAt(ZoneList* args) { +void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); VisitForStackValue(args->at(0)); @@ -2948,7 +2964,8 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList* args) { } -void FullCodeGenerator::EmitStringAdd(ZoneList* args) { +void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); VisitForStackValue(args->at(0)); @@ -2960,7 +2977,8 @@ void FullCodeGenerator::EmitStringAdd(ZoneList* args) { } -void FullCodeGenerator::EmitStringCompare(ZoneList* args) { +void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); VisitForStackValue(args->at(0)); @@ -2972,10 +2990,11 @@ void FullCodeGenerator::EmitStringCompare(ZoneList* args) { } -void FullCodeGenerator::EmitMathSin(ZoneList* args) { +void FullCodeGenerator::EmitMathSin(CallRuntime* expr) { // Load the argument on the stack and call the stub. TranscendentalCacheStub stub(TranscendentalCache::SIN, TranscendentalCacheStub::TAGGED); + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallStub(&stub); @@ -2983,10 +3002,11 @@ void FullCodeGenerator::EmitMathSin(ZoneList* args) { } -void FullCodeGenerator::EmitMathCos(ZoneList* args) { +void FullCodeGenerator::EmitMathCos(CallRuntime* expr) { // Load the argument on the stack and call the stub. TranscendentalCacheStub stub(TranscendentalCache::COS, TranscendentalCacheStub::TAGGED); + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallStub(&stub); @@ -2994,10 +3014,11 @@ void FullCodeGenerator::EmitMathCos(ZoneList* args) { } -void FullCodeGenerator::EmitMathLog(ZoneList* args) { +void FullCodeGenerator::EmitMathLog(CallRuntime* expr) { // Load the argument on the stack and call the stub. TranscendentalCacheStub stub(TranscendentalCache::LOG, TranscendentalCacheStub::TAGGED); + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallStub(&stub); @@ -3005,8 +3026,9 @@ void FullCodeGenerator::EmitMathLog(ZoneList* args) { } -void FullCodeGenerator::EmitMathSqrt(ZoneList* args) { +void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) { // Load the argument on the stack and call the runtime function. + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForStackValue(args->at(0)); __ CallRuntime(Runtime::kMath_sqrt, 1); @@ -3014,7 +3036,8 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList* args) { } -void FullCodeGenerator::EmitCallFunction(ZoneList* args) { +void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() >= 2); int arg_count = args->length() - 2; // 2 ~ receiver and function. @@ -3033,8 +3056,9 @@ void FullCodeGenerator::EmitCallFunction(ZoneList* args) { } -void FullCodeGenerator::EmitRegExpConstructResult(ZoneList* args) { +void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { RegExpConstructResultStub stub; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -3044,7 +3068,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList* args) { } -void FullCodeGenerator::EmitSwapElements(ZoneList* args) { +void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -3139,7 +3164,8 @@ void FullCodeGenerator::EmitSwapElements(ZoneList* args) { } -void FullCodeGenerator::EmitGetFromCache(ZoneList* args) { +void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); ASSERT_NE(NULL, args->at(0)->AsLiteral()); @@ -3195,7 +3221,8 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList* args) { } -void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList* args) { +void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT_EQ(2, args->length()); Register right = rax; @@ -3233,7 +3260,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList* args) { } -void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { +void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3247,7 +3275,7 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { __ testl(FieldOperand(rax, String::kHashFieldOffset), Immediate(String::kContainsCachedArrayIndexMask)); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); __ j(zero, if_true); __ jmp(if_false); @@ -3255,7 +3283,8 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { } -void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList* args) { +void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { + ZoneList* args = expr->arguments(); ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3271,10 +3300,11 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList* args) { } -void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList* args) { +void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { Label bailout, return_result, done, one_char_separator, long_separator, non_trivial_array, not_size_one_array, loop, loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; + ZoneList* args = expr->arguments(); ASSERT(args->length() == 2); // We will leave the separator on the stack until the end of the function. 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 // subexpression. Match the optimizing compiler by not branching. 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 { - Label materialize_true, materialize_false; - Label* if_true = NULL; - Label* if_false = NULL; - Label* fall_through = NULL; - // Notice that the labels are swapped. - context()->PrepareTest(&materialize_true, &materialize_false, - &if_false, &if_true, &fall_through); - if (context()->IsTest()) ForwardBailoutToChild(expr); - VisitForControl(expr->expression(), if_true, if_false, fall_through); - context()->Plug(if_false, if_true); // Labels swapped. + // We handle value contexts explicitly rather than simply visiting + // for control and plugging the control flow into the context, + // because we need to prepare a pair of extra administrative AST ids + // for the optimizing compiler. + ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); + Label materialize_true, materialize_false, done; + VisitForControl(expr->expression(), + &materialize_false, + &materialize_true, + &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; } @@ -3935,12 +3989,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { context()->Plug(rax); } else { // This expression cannot throw a reference error at the top level. - VisitInCurrentContext(expr); + VisitInDuplicateContext(expr); } } void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, + Expression* sub_expr, Handle check) { Label materialize_true, materialize_false; Label* if_true = NULL; @@ -3950,9 +4005,9 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, &if_true, &if_false, &fall_through); { 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())) { __ JumpIfSmi(rax, if_true); @@ -4036,7 +4091,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { case Token::IN: VisitForStackValue(expr->right()); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); - PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); __ CompareRoot(rax, Heap::kTrueValueRootIndex); Split(equal, if_true, if_false, fall_through); break; @@ -4045,7 +4100,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { VisitForStackValue(expr->right()); InstanceofStub stub(InstanceofStub::kNoFlags); __ CallStub(&stub); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); __ testq(rax, rax); // The stub returns 0 for true. Split(zero, if_true, if_false, fall_through); @@ -4097,7 +4152,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { __ call(ic, RelocInfo::CODE_TARGET, expr->id()); patch_site.EmitPatchInfo(); - PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); + PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); __ testq(rax, rax); Split(cc, if_true, if_false, fall_through); } @@ -4120,7 +4175,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, &if_true, &if_false, &fall_through); 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::kNullValueRootIndex : Heap::kUndefinedValueRootIndex;