Remove the forward-bailout stack from the non-optimizing compiler.
This was pretty heavyweight. It was kept in just for a few corner cases that assumed it was there. We can work around them by making sure that the expression in a reified test context is always really the expression that was visited in that context; and by inspecting the context manually and consing up a pair of extra AST IDs for the unusual case of unary not in a value AST context. R=fschneider@chromium.org BUG= TEST= Review URL: http://codereview.chromium.org/8386037 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9863 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
307b589e61
commit
4e4a901d96
@ -394,7 +394,7 @@ void FullCodeGenerator::TestContext::Plug(Variable* var) const {
|
|||||||
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
|
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
|
||||||
// For simplicity we always test the accumulator register.
|
// For simplicity we always test the accumulator register.
|
||||||
codegen()->GetVar(result_register(), var);
|
codegen()->GetVar(result_register(), var);
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +417,7 @@ void FullCodeGenerator::StackValueContext::Plug(
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
|
void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
|
codegen()->PrepareForBailoutBeforeSplit(condition(),
|
||||||
true,
|
true,
|
||||||
true_label_,
|
true_label_,
|
||||||
false_label_);
|
false_label_);
|
||||||
@ -452,7 +452,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
|
void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
|
codegen()->PrepareForBailoutBeforeSplit(condition(),
|
||||||
true,
|
true,
|
||||||
true_label_,
|
true_label_,
|
||||||
false_label_);
|
false_label_);
|
||||||
@ -511,7 +511,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
|
|||||||
// For simplicity we always test the accumulator register.
|
// For simplicity we always test the accumulator register.
|
||||||
__ Drop(count);
|
__ Drop(count);
|
||||||
__ Move(result_register(), reg);
|
__ Move(result_register(), reg);
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +578,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::TestContext::Plug(bool flag) const {
|
void FullCodeGenerator::TestContext::Plug(bool flag) const {
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
|
codegen()->PrepareForBailoutBeforeSplit(condition(),
|
||||||
true,
|
true,
|
||||||
true_label_,
|
true_label_,
|
||||||
false_label_);
|
false_label_);
|
||||||
@ -681,7 +681,7 @@ void FullCodeGenerator::SetVar(Variable* var,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
|
||||||
bool should_normalize,
|
bool should_normalize,
|
||||||
Label* if_true,
|
Label* if_true,
|
||||||
Label* if_false) {
|
Label* if_false) {
|
||||||
@ -692,13 +692,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
|||||||
|
|
||||||
Label skip;
|
Label skip;
|
||||||
if (should_normalize) __ b(&skip);
|
if (should_normalize) __ b(&skip);
|
||||||
|
PrepareForBailout(expr, TOS_REG);
|
||||||
ForwardBailoutStack* current = forward_bailout_stack_;
|
|
||||||
while (current != NULL) {
|
|
||||||
PrepareForBailout(current->expr(), state);
|
|
||||||
current = current->parent();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (should_normalize) {
|
if (should_normalize) {
|
||||||
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
||||||
__ cmp(r0, ip);
|
__ cmp(r0, ip);
|
||||||
@ -2377,7 +2371,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2389,7 +2384,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
|||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ tst(r0, Operand(kSmiTagMask));
|
__ tst(r0, Operand(kSmiTagMask));
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2397,7 +2392,8 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2409,7 +2405,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
|||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ tst(r0, Operand(kSmiTagMask | 0x80000000));
|
__ tst(r0, Operand(kSmiTagMask | 0x80000000));
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2417,7 +2413,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2442,14 +2439,15 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
|||||||
__ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
__ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
||||||
__ b(lt, if_false);
|
__ b(lt, if_false);
|
||||||
__ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
__ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(le, if_true, if_false, fall_through);
|
Split(le, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2463,14 +2461,15 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(r0, if_false);
|
__ JumpIfSmi(r0, if_false);
|
||||||
__ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
|
__ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(ge, if_true, if_false, fall_through);
|
Split(ge, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2486,7 +2485,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
|||||||
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
|
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
|
||||||
__ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
|
__ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
|
||||||
__ tst(r1, Operand(1 << Map::kIsUndetectable));
|
__ tst(r1, Operand(1 << Map::kIsUndetectable));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(ne, if_true, if_false, fall_through);
|
Split(ne, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -2494,8 +2493,8 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
||||||
ZoneList<Expression*>* args) {
|
CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2574,12 +2573,13 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
|||||||
__ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
|
__ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
|
||||||
__ jmp(if_true);
|
__ jmp(if_true);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2593,14 +2593,15 @@ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(r0, if_false);
|
__ JumpIfSmi(r0, if_false);
|
||||||
__ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
|
__ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2614,14 +2615,15 @@ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(r0, if_false);
|
__ JumpIfSmi(r0, if_false);
|
||||||
__ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
|
__ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2635,7 +2637,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(r0, if_false);
|
__ JumpIfSmi(r0, if_false);
|
||||||
__ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
|
__ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -2643,8 +2645,8 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
|
||||||
ASSERT(args->length() == 0);
|
ASSERT(expr->arguments()->length() == 0);
|
||||||
|
|
||||||
Label materialize_true, materialize_false;
|
Label materialize_true, materialize_false;
|
||||||
Label* if_true = NULL;
|
Label* if_true = NULL;
|
||||||
@ -2667,14 +2669,15 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
|
|||||||
__ bind(&check_frame_marker);
|
__ bind(&check_frame_marker);
|
||||||
__ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
|
__ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
|
||||||
__ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
|
__ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
// Load the two objects into registers and perform the comparison.
|
// Load the two objects into registers and perform the comparison.
|
||||||
@ -2690,14 +2693,15 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ pop(r1);
|
__ pop(r1);
|
||||||
__ cmp(r0, r1);
|
__ cmp(r0, r1);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
// ArgumentsAccessStub expects the key in edx and the formal
|
// ArgumentsAccessStub expects the key in edx and the formal
|
||||||
@ -2711,9 +2715,8 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
|
||||||
ASSERT(args->length() == 0);
|
ASSERT(expr->arguments()->length() == 0);
|
||||||
|
|
||||||
Label exit;
|
Label exit;
|
||||||
// Get the number of formal parameters.
|
// Get the number of formal parameters.
|
||||||
__ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
|
__ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
|
||||||
@ -2733,7 +2736,8 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
Label done, null, function, non_function_constructor;
|
Label done, null, function, non_function_constructor;
|
||||||
|
|
||||||
@ -2793,7 +2797,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitLog(CallRuntime* expr) {
|
||||||
// Conditionally generate a log call.
|
// Conditionally generate a log call.
|
||||||
// Args:
|
// Args:
|
||||||
// 0 (literal string): The type of logging (corresponds to the flags).
|
// 0 (literal string): The type of logging (corresponds to the flags).
|
||||||
@ -2801,6 +2805,7 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
|||||||
// 1 (string): Format string. Access the string at argument index 2
|
// 1 (string): Format string. Access the string at argument index 2
|
||||||
// with '%2s' (see Logger::LogRuntime for all the formats).
|
// with '%2s' (see Logger::LogRuntime for all the formats).
|
||||||
// 2 (array): Arguments to the format string.
|
// 2 (array): Arguments to the format string.
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(args->length(), 3);
|
ASSERT_EQ(args->length(), 3);
|
||||||
if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
|
if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2814,9 +2819,8 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
|
||||||
ASSERT(args->length() == 0);
|
ASSERT(expr->arguments()->length() == 0);
|
||||||
|
|
||||||
Label slow_allocate_heapnumber;
|
Label slow_allocate_heapnumber;
|
||||||
Label heapnumber_allocated;
|
Label heapnumber_allocated;
|
||||||
|
|
||||||
@ -2868,9 +2872,10 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the stub.
|
// Load the arguments on the stack and call the stub.
|
||||||
SubStringStub stub;
|
SubStringStub stub;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 3);
|
ASSERT(args->length() == 3);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2880,9 +2885,10 @@ void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the stub.
|
// Load the arguments on the stack and call the stub.
|
||||||
RegExpExecStub stub;
|
RegExpExecStub stub;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 4);
|
ASSERT(args->length() == 4);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2893,9 +2899,9 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0)); // Load the object.
|
VisitForAccumulatorValue(args->at(0)); // Load the object.
|
||||||
|
|
||||||
Label done;
|
Label done;
|
||||||
@ -2911,8 +2917,9 @@ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the runtime function.
|
// Load the arguments on the stack and call the runtime function.
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2922,9 +2929,9 @@ void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
VisitForStackValue(args->at(0)); // Load the object.
|
VisitForStackValue(args->at(0)); // Load the object.
|
||||||
VisitForAccumulatorValue(args->at(1)); // Load the value.
|
VisitForAccumulatorValue(args->at(1)); // Load the value.
|
||||||
__ pop(r1); // r0 = value. r1 = object.
|
__ pop(r1); // r0 = value. r1 = object.
|
||||||
@ -2950,9 +2957,9 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(args->length(), 1);
|
ASSERT_EQ(args->length(), 1);
|
||||||
|
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
|
|
||||||
@ -2962,9 +2969,9 @@ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
|
|
||||||
Label done;
|
Label done;
|
||||||
@ -2980,9 +2987,9 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForAccumulatorValue(args->at(1));
|
VisitForAccumulatorValue(args->at(1));
|
||||||
|
|
||||||
@ -3027,9 +3034,9 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForAccumulatorValue(args->at(1));
|
VisitForAccumulatorValue(args->at(1));
|
||||||
|
|
||||||
@ -3076,9 +3083,9 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
|
|
||||||
@ -3088,9 +3095,9 @@ void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
|
|
||||||
@ -3100,10 +3107,11 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
||||||
TranscendentalCacheStub::TAGGED);
|
TranscendentalCacheStub::TAGGED);
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
@ -3111,10 +3119,11 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
TranscendentalCacheStub stub(TranscendentalCache::COS,
|
TranscendentalCacheStub stub(TranscendentalCache::COS,
|
||||||
TranscendentalCacheStub::TAGGED);
|
TranscendentalCacheStub::TAGGED);
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
@ -3122,10 +3131,11 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
||||||
TranscendentalCacheStub::TAGGED);
|
TranscendentalCacheStub::TAGGED);
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
@ -3133,8 +3143,9 @@ void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the runtime function.
|
// Load the argument on the stack and call the runtime function.
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallRuntime(Runtime::kMath_sqrt, 1);
|
__ CallRuntime(Runtime::kMath_sqrt, 1);
|
||||||
@ -3142,7 +3153,8 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() >= 2);
|
ASSERT(args->length() >= 2);
|
||||||
|
|
||||||
int arg_count = args->length() - 2; // 2 ~ receiver and function.
|
int arg_count = args->length() - 2; // 2 ~ receiver and function.
|
||||||
@ -3161,8 +3173,9 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
|
||||||
RegExpConstructResultStub stub;
|
RegExpConstructResultStub stub;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 3);
|
ASSERT(args->length() == 3);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -3172,7 +3185,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 3);
|
ASSERT(args->length() == 3);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -3269,9 +3283,9 @@ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
ASSERT_NE(NULL, args->at(0)->AsLiteral());
|
ASSERT_NE(NULL, args->at(0)->AsLiteral());
|
||||||
int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
|
int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
|
||||||
|
|
||||||
@ -3320,7 +3334,8 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
Register right = r0;
|
Register right = r0;
|
||||||
@ -3360,7 +3375,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
|
|
||||||
Label materialize_true, materialize_false;
|
Label materialize_true, materialize_false;
|
||||||
@ -3372,14 +3388,15 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
|
__ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
|
||||||
__ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
|
__ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
|
|
||||||
@ -3394,12 +3411,12 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
||||||
Label bailout, done, one_char_separator, long_separator,
|
Label bailout, done, one_char_separator, long_separator,
|
||||||
non_trivial_array, not_size_one_array, loop,
|
non_trivial_array, not_size_one_array, loop,
|
||||||
empty_separator_loop, one_char_separator_loop,
|
empty_separator_loop, one_char_separator_loop,
|
||||||
one_char_separator_loop_entry, long_separator_loop;
|
one_char_separator_loop_entry, long_separator_loop;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -3727,18 +3744,35 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
// Unary NOT has no side effects so it's only necessary to visit the
|
// Unary NOT has no side effects so it's only necessary to visit the
|
||||||
// subexpression. Match the optimizing compiler by not branching.
|
// subexpression. Match the optimizing compiler by not branching.
|
||||||
VisitForEffect(expr->expression());
|
VisitForEffect(expr->expression());
|
||||||
|
} else if (context()->IsTest()) {
|
||||||
|
const TestContext* test = TestContext::cast(context());
|
||||||
|
// The labels are swapped for the recursive call.
|
||||||
|
VisitForControl(expr->expression(),
|
||||||
|
test->false_label(),
|
||||||
|
test->true_label(),
|
||||||
|
test->fall_through());
|
||||||
|
context()->Plug(test->true_label(), test->false_label());
|
||||||
} else {
|
} else {
|
||||||
Label materialize_true, materialize_false;
|
// We handle value contexts explicitly rather than simply visiting
|
||||||
Label* if_true = NULL;
|
// for control and plugging the control flow into the context,
|
||||||
Label* if_false = NULL;
|
// because we need to prepare a pair of extra administrative AST ids
|
||||||
Label* fall_through = NULL;
|
// for the optimizing compiler.
|
||||||
|
ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
|
||||||
// Notice that the labels are swapped.
|
Label materialize_true, materialize_false, done;
|
||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
VisitForControl(expr->expression(),
|
||||||
&if_false, &if_true, &fall_through);
|
&materialize_false,
|
||||||
if (context()->IsTest()) ForwardBailoutToChild(expr);
|
&materialize_true,
|
||||||
VisitForControl(expr->expression(), if_true, if_false, fall_through);
|
&materialize_true);
|
||||||
context()->Plug(if_false, if_true); // Labels swapped.
|
__ bind(&materialize_true);
|
||||||
|
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
|
||||||
|
__ LoadRoot(r0, Heap::kTrueValueRootIndex);
|
||||||
|
if (context()->IsStackValue()) __ push(r0);
|
||||||
|
__ jmp(&done);
|
||||||
|
__ bind(&materialize_false);
|
||||||
|
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
|
||||||
|
__ LoadRoot(r0, Heap::kFalseValueRootIndex);
|
||||||
|
if (context()->IsStackValue()) __ push(r0);
|
||||||
|
__ bind(&done);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3997,12 +4031,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|||||||
context()->Plug(r0);
|
context()->Plug(r0);
|
||||||
} else {
|
} else {
|
||||||
// This expression cannot throw a reference error at the top level.
|
// This expression cannot throw a reference error at the top level.
|
||||||
VisitInCurrentContext(expr);
|
VisitInDuplicateContext(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
Label materialize_true, materialize_false;
|
Label materialize_true, materialize_false;
|
||||||
Label* if_true = NULL;
|
Label* if_true = NULL;
|
||||||
@ -4012,9 +4047,9 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
|||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
{ AccumulatorValueContext context(this);
|
{ AccumulatorValueContext context(this);
|
||||||
VisitForTypeofValue(expr);
|
VisitForTypeofValue(sub_expr);
|
||||||
}
|
}
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
|
|
||||||
if (check->Equals(isolate()->heap()->number_symbol())) {
|
if (check->Equals(isolate()->heap()->number_symbol())) {
|
||||||
__ JumpIfSmi(r0, if_true);
|
__ JumpIfSmi(r0, if_true);
|
||||||
@ -4101,7 +4136,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
case Token::IN:
|
case Token::IN:
|
||||||
VisitForStackValue(expr->right());
|
VisitForStackValue(expr->right());
|
||||||
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
|
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
|
||||||
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
||||||
__ cmp(r0, ip);
|
__ cmp(r0, ip);
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
@ -4111,7 +4146,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
VisitForStackValue(expr->right());
|
VisitForStackValue(expr->right());
|
||||||
InstanceofStub stub(InstanceofStub::kNoFlags);
|
InstanceofStub stub(InstanceofStub::kNoFlags);
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
// The stub returns 0 for true.
|
// The stub returns 0 for true.
|
||||||
__ tst(r0, r0);
|
__ tst(r0, r0);
|
||||||
Split(eq, if_true, if_false, fall_through);
|
Split(eq, if_true, if_false, fall_through);
|
||||||
@ -4161,7 +4196,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
Handle<Code> ic = CompareIC::GetUninitialized(op);
|
Handle<Code> ic = CompareIC::GetUninitialized(op);
|
||||||
__ Call(ic, RelocInfo::CODE_TARGET, expr->id());
|
__ Call(ic, RelocInfo::CODE_TARGET, expr->id());
|
||||||
patch_site.EmitPatchInfo();
|
patch_site.EmitPatchInfo();
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ cmp(r0, Operand(0));
|
__ cmp(r0, Operand(0));
|
||||||
Split(cond, if_true, if_false, fall_through);
|
Split(cond, if_true, if_false, fall_through);
|
||||||
}
|
}
|
||||||
@ -4184,7 +4219,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
|
|||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
VisitForAccumulatorValue(sub_expr);
|
VisitForAccumulatorValue(sub_expr);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Heap::RootListIndex nil_value = nil == kNullValue ?
|
Heap::RootListIndex nil_value = nil == kNullValue ?
|
||||||
Heap::kNullValueRootIndex :
|
Heap::kNullValueRootIndex :
|
||||||
Heap::kUndefinedValueRootIndex;
|
Heap::kUndefinedValueRootIndex;
|
||||||
|
19
src/ast.h
19
src/ast.h
@ -1288,8 +1288,17 @@ class UnaryOperation: public Expression {
|
|||||||
Token::Value op,
|
Token::Value op,
|
||||||
Expression* expression,
|
Expression* expression,
|
||||||
int pos)
|
int pos)
|
||||||
: Expression(isolate), op_(op), expression_(expression), pos_(pos) {
|
: Expression(isolate),
|
||||||
|
op_(op),
|
||||||
|
expression_(expression),
|
||||||
|
pos_(pos),
|
||||||
|
materialize_true_id_(AstNode::kNoNumber),
|
||||||
|
materialize_false_id_(AstNode::kNoNumber) {
|
||||||
ASSERT(Token::IsUnaryOp(op));
|
ASSERT(Token::IsUnaryOp(op));
|
||||||
|
if (op == Token::NOT) {
|
||||||
|
materialize_true_id_ = GetNextId(isolate);
|
||||||
|
materialize_false_id_ = GetNextId(isolate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_NODE_TYPE(UnaryOperation)
|
DECLARE_NODE_TYPE(UnaryOperation)
|
||||||
@ -1302,10 +1311,18 @@ class UnaryOperation: public Expression {
|
|||||||
Expression* expression() const { return expression_; }
|
Expression* expression() const { return expression_; }
|
||||||
virtual int position() const { return pos_; }
|
virtual int position() const { return pos_; }
|
||||||
|
|
||||||
|
int MaterializeTrueId() { return materialize_true_id_; }
|
||||||
|
int MaterializeFalseId() { return materialize_false_id_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Token::Value op_;
|
Token::Value op_;
|
||||||
Expression* expression_;
|
Expression* expression_;
|
||||||
int pos_;
|
int pos_;
|
||||||
|
|
||||||
|
// For unary not (Token::NOT), the AST ids where true and false will
|
||||||
|
// actually be materialized, respectively.
|
||||||
|
int materialize_true_id_;
|
||||||
|
int materialize_false_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -416,7 +416,7 @@ void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
|
|||||||
void FullCodeGenerator::TestContext::Plug(Register reg) const {
|
void FullCodeGenerator::TestContext::Plug(Register reg) const {
|
||||||
// For simplicity we always test the accumulator register.
|
// For simplicity we always test the accumulator register.
|
||||||
__ Move(result_register(), reg);
|
__ Move(result_register(), reg);
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +438,7 @@ void FullCodeGenerator::StackValueContext::PlugTOS() const {
|
|||||||
void FullCodeGenerator::TestContext::PlugTOS() const {
|
void FullCodeGenerator::TestContext::PlugTOS() const {
|
||||||
// For simplicity we always test the accumulator register.
|
// For simplicity we always test the accumulator register.
|
||||||
__ pop(result_register());
|
__ pop(result_register());
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,14 +652,13 @@ FullCodeGenerator::InlineFunctionGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
|
void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
|
||||||
ZoneList<Expression*>* args = node->arguments();
|
const Runtime::Function* function = expr->function();
|
||||||
const Runtime::Function* function = node->function();
|
|
||||||
ASSERT(function != NULL);
|
ASSERT(function != NULL);
|
||||||
ASSERT(function->intrinsic_type == Runtime::INLINE);
|
ASSERT(function->intrinsic_type == Runtime::INLINE);
|
||||||
InlineFunctionGenerator generator =
|
InlineFunctionGenerator generator =
|
||||||
FindInlineFunctionGenerator(function->function_id);
|
FindInlineFunctionGenerator(function->function_id);
|
||||||
((*this).*(generator))(args);
|
((*this).*(generator))(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -676,11 +675,25 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
|
||||||
|
if (context()->IsEffect()) {
|
||||||
|
VisitForEffect(expr);
|
||||||
|
} else if (context()->IsAccumulatorValue()) {
|
||||||
|
VisitForAccumulatorValue(expr);
|
||||||
|
} else if (context()->IsStackValue()) {
|
||||||
|
VisitForStackValue(expr);
|
||||||
|
} else if (context()->IsTest()) {
|
||||||
|
const TestContext* test = TestContext::cast(context());
|
||||||
|
VisitForControl(expr, test->true_label(), test->false_label(),
|
||||||
|
test->fall_through());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
|
void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
|
||||||
Comment cmnt(masm_, "[ Comma");
|
Comment cmnt(masm_, "[ Comma");
|
||||||
VisitForEffect(expr->left());
|
VisitForEffect(expr->left());
|
||||||
if (context()->IsTest()) ForwardBailoutToChild(expr);
|
VisitInDuplicateContext(expr->right());
|
||||||
VisitInCurrentContext(expr->right());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -702,7 +715,6 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
|
|||||||
}
|
}
|
||||||
PrepareForBailoutForId(right_id, NO_REGISTERS);
|
PrepareForBailoutForId(right_id, NO_REGISTERS);
|
||||||
__ bind(&eval_right);
|
__ bind(&eval_right);
|
||||||
ForwardBailoutToChild(expr);
|
|
||||||
|
|
||||||
} else if (context()->IsAccumulatorValue()) {
|
} else if (context()->IsAccumulatorValue()) {
|
||||||
VisitForAccumulatorValue(left);
|
VisitForAccumulatorValue(left);
|
||||||
@ -710,7 +722,6 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
|
|||||||
// case we need it.
|
// case we need it.
|
||||||
__ push(result_register());
|
__ push(result_register());
|
||||||
Label discard, restore;
|
Label discard, restore;
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
|
||||||
if (is_logical_and) {
|
if (is_logical_and) {
|
||||||
DoTest(left, &discard, &restore, &restore);
|
DoTest(left, &discard, &restore, &restore);
|
||||||
} else {
|
} else {
|
||||||
@ -729,7 +740,6 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
|
|||||||
// case we need it.
|
// case we need it.
|
||||||
__ push(result_register());
|
__ push(result_register());
|
||||||
Label discard;
|
Label discard;
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
|
||||||
if (is_logical_and) {
|
if (is_logical_and) {
|
||||||
DoTest(left, &discard, &done, &discard);
|
DoTest(left, &discard, &done, &discard);
|
||||||
} else {
|
} else {
|
||||||
@ -751,7 +761,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
|
|||||||
__ bind(&eval_right);
|
__ bind(&eval_right);
|
||||||
}
|
}
|
||||||
|
|
||||||
VisitInCurrentContext(right);
|
VisitInDuplicateContext(right);
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,34 +788,6 @@ void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::ForwardBailoutToChild(Expression* expr) {
|
|
||||||
if (!info_->HasDeoptimizationSupport()) return;
|
|
||||||
ASSERT(context()->IsTest());
|
|
||||||
ASSERT(expr == forward_bailout_stack_->expr());
|
|
||||||
forward_bailout_pending_ = forward_bailout_stack_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitInCurrentContext(Expression* expr) {
|
|
||||||
if (context()->IsTest()) {
|
|
||||||
ForwardBailoutStack stack(expr, forward_bailout_pending_);
|
|
||||||
ForwardBailoutStack* saved = forward_bailout_stack_;
|
|
||||||
forward_bailout_pending_ = NULL;
|
|
||||||
forward_bailout_stack_ = &stack;
|
|
||||||
Visit(expr);
|
|
||||||
forward_bailout_stack_ = saved;
|
|
||||||
} else {
|
|
||||||
ASSERT(forward_bailout_pending_ == NULL);
|
|
||||||
Visit(expr);
|
|
||||||
State state = context()->IsAccumulatorValue() ? TOS_REG : NO_REGISTERS;
|
|
||||||
PrepareForBailout(expr, state);
|
|
||||||
// Forwarding bailouts to children is a one shot operation. It should have
|
|
||||||
// been processed at this point.
|
|
||||||
ASSERT(forward_bailout_pending_ == NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitBlock(Block* stmt) {
|
void FullCodeGenerator::VisitBlock(Block* stmt) {
|
||||||
Comment cmnt(masm_, "[ Block");
|
Comment cmnt(masm_, "[ Block");
|
||||||
NestedBlock nested_block(this, stmt);
|
NestedBlock nested_block(this, stmt);
|
||||||
@ -1247,16 +1229,15 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
|
|||||||
for_test->false_label(),
|
for_test->false_label(),
|
||||||
NULL);
|
NULL);
|
||||||
} else {
|
} else {
|
||||||
VisitInCurrentContext(expr->then_expression());
|
VisitInDuplicateContext(expr->then_expression());
|
||||||
__ jmp(&done);
|
__ jmp(&done);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
|
PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
|
||||||
__ bind(&false_case);
|
__ bind(&false_case);
|
||||||
if (context()->IsTest()) ForwardBailoutToChild(expr);
|
|
||||||
SetExpressionPosition(expr->else_expression(),
|
SetExpressionPosition(expr->else_expression(),
|
||||||
expr->else_expression_position());
|
expr->else_expression_position());
|
||||||
VisitInCurrentContext(expr->else_expression());
|
VisitInDuplicateContext(expr->else_expression());
|
||||||
// If control flow falls through Visit, merge it with true case here.
|
// If control flow falls through Visit, merge it with true case here.
|
||||||
if (!context()->IsTest()) {
|
if (!context()->IsTest()) {
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
@ -1314,7 +1295,7 @@ bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
|
|||||||
Expression *sub_expr;
|
Expression *sub_expr;
|
||||||
Handle<String> check;
|
Handle<String> check;
|
||||||
if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
|
if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
|
||||||
EmitLiteralCompareTypeof(sub_expr, check);
|
EmitLiteralCompareTypeof(expr, sub_expr, check);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +85,7 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
loop_depth_(0),
|
loop_depth_(0),
|
||||||
context_(NULL),
|
context_(NULL),
|
||||||
bailout_entries_(0),
|
bailout_entries_(0),
|
||||||
stack_checks_(2), // There's always at least one.
|
stack_checks_(2) { // There's always at least one.
|
||||||
forward_bailout_stack_(NULL),
|
|
||||||
forward_bailout_pending_(NULL) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool MakeCode(CompilationInfo* info);
|
static bool MakeCode(CompilationInfo* info);
|
||||||
@ -275,27 +273,8 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// The forward bailout stack keeps track of the expressions that can
|
|
||||||
// bail out to just before the control flow is split in a child
|
|
||||||
// node. The stack elements are linked together through the parent
|
|
||||||
// link when visiting expressions in test contexts after requesting
|
|
||||||
// bailout in child forwarding.
|
|
||||||
class ForwardBailoutStack BASE_EMBEDDED {
|
|
||||||
public:
|
|
||||||
ForwardBailoutStack(Expression* expr, ForwardBailoutStack* parent)
|
|
||||||
: expr_(expr), parent_(parent) { }
|
|
||||||
|
|
||||||
Expression* expr() const { return expr_; }
|
|
||||||
ForwardBailoutStack* parent() const { return parent_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Expression* const expr_;
|
|
||||||
ForwardBailoutStack* const parent_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Type of a member function that generates inline code for a native function.
|
// Type of a member function that generates inline code for a native function.
|
||||||
typedef void (FullCodeGenerator::*InlineFunctionGenerator)
|
typedef void (FullCodeGenerator::*InlineFunctionGenerator)(CallRuntime* expr);
|
||||||
(ZoneList<Expression*>*);
|
|
||||||
|
|
||||||
static const InlineFunctionGenerator kInlineFunctionGenerators[];
|
static const InlineFunctionGenerator kInlineFunctionGenerators[];
|
||||||
|
|
||||||
@ -356,23 +335,22 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
// need the write barrier if location is CONTEXT.
|
// need the write barrier if location is CONTEXT.
|
||||||
MemOperand VarOperand(Variable* var, Register scratch);
|
MemOperand VarOperand(Variable* var, Register scratch);
|
||||||
|
|
||||||
// Forward the bailout responsibility for the given expression to
|
|
||||||
// the next child visited (which must be in a test context).
|
|
||||||
void ForwardBailoutToChild(Expression* expr);
|
|
||||||
|
|
||||||
void VisitForEffect(Expression* expr) {
|
void VisitForEffect(Expression* expr) {
|
||||||
EffectContext context(this);
|
EffectContext context(this);
|
||||||
VisitInCurrentContext(expr);
|
Visit(expr);
|
||||||
|
PrepareForBailout(expr, NO_REGISTERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisitForAccumulatorValue(Expression* expr) {
|
void VisitForAccumulatorValue(Expression* expr) {
|
||||||
AccumulatorValueContext context(this);
|
AccumulatorValueContext context(this);
|
||||||
VisitInCurrentContext(expr);
|
Visit(expr);
|
||||||
|
PrepareForBailout(expr, TOS_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisitForStackValue(Expression* expr) {
|
void VisitForStackValue(Expression* expr) {
|
||||||
StackValueContext context(this);
|
StackValueContext context(this);
|
||||||
VisitInCurrentContext(expr);
|
Visit(expr);
|
||||||
|
PrepareForBailout(expr, NO_REGISTERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisitForControl(Expression* expr,
|
void VisitForControl(Expression* expr,
|
||||||
@ -380,9 +358,14 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
Label* if_false,
|
Label* if_false,
|
||||||
Label* fall_through) {
|
Label* fall_through) {
|
||||||
TestContext context(this, expr, if_true, if_false, fall_through);
|
TestContext context(this, expr, if_true, if_false, fall_through);
|
||||||
VisitInCurrentContext(expr);
|
Visit(expr);
|
||||||
|
// For test contexts, we prepare for bailout before branching, not at
|
||||||
|
// the end of the entire expression. This happens as part of visiting
|
||||||
|
// the expression.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VisitInDuplicateContext(Expression* expr);
|
||||||
|
|
||||||
void VisitDeclarations(ZoneList<Declaration*>* declarations);
|
void VisitDeclarations(ZoneList<Declaration*>* declarations);
|
||||||
void DeclareGlobals(Handle<FixedArray> pairs);
|
void DeclareGlobals(Handle<FixedArray> pairs);
|
||||||
int DeclareGlobalsFlags();
|
int DeclareGlobalsFlags();
|
||||||
@ -394,7 +377,9 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
|
|
||||||
// Platform-specific code for comparing the type of a value with
|
// Platform-specific code for comparing the type of a value with
|
||||||
// a given literal string.
|
// a given literal string.
|
||||||
void EmitLiteralCompareTypeof(Expression* expr, Handle<String> check);
|
void EmitLiteralCompareTypeof(Expression* expr,
|
||||||
|
Expression* sub_expr,
|
||||||
|
Handle<String> check);
|
||||||
|
|
||||||
// Platform-specific code for equality comparison with a nil-like value.
|
// Platform-specific code for equality comparison with a nil-like value.
|
||||||
void EmitLiteralCompareNil(CompareOperation* expr,
|
void EmitLiteralCompareNil(CompareOperation* expr,
|
||||||
@ -414,7 +399,7 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
// canonical JS true value so we will insert a (dead) test against true at
|
// canonical JS true value so we will insert a (dead) test against true at
|
||||||
// the actual bailout target from the optimized code. If not
|
// the actual bailout target from the optimized code. If not
|
||||||
// should_normalize, the true and false labels are ignored.
|
// should_normalize, the true and false labels are ignored.
|
||||||
void PrepareForBailoutBeforeSplit(State state,
|
void PrepareForBailoutBeforeSplit(Expression* expr,
|
||||||
bool should_normalize,
|
bool should_normalize,
|
||||||
Label* if_true,
|
Label* if_true,
|
||||||
Label* if_false);
|
Label* if_false);
|
||||||
@ -449,7 +434,7 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
void EmitInlineRuntimeCall(CallRuntime* expr);
|
void EmitInlineRuntimeCall(CallRuntime* expr);
|
||||||
|
|
||||||
#define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
|
#define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
|
||||||
void Emit##name(ZoneList<Expression*>* arguments);
|
void Emit##name(CallRuntime* expr);
|
||||||
INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
|
INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
|
||||||
INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
|
INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
|
||||||
#undef EMIT_INLINE_RUNTIME_CALL
|
#undef EMIT_INLINE_RUNTIME_CALL
|
||||||
@ -576,7 +561,6 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
void VisitComma(BinaryOperation* expr);
|
void VisitComma(BinaryOperation* expr);
|
||||||
void VisitLogicalExpression(BinaryOperation* expr);
|
void VisitLogicalExpression(BinaryOperation* expr);
|
||||||
void VisitArithmeticExpression(BinaryOperation* expr);
|
void VisitArithmeticExpression(BinaryOperation* expr);
|
||||||
void VisitInCurrentContext(Expression* expr);
|
|
||||||
|
|
||||||
void VisitForTypeofValue(Expression* expr);
|
void VisitForTypeofValue(Expression* expr);
|
||||||
|
|
||||||
@ -771,8 +755,6 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
const ExpressionContext* context_;
|
const ExpressionContext* context_;
|
||||||
ZoneList<BailoutEntry> bailout_entries_;
|
ZoneList<BailoutEntry> bailout_entries_;
|
||||||
ZoneList<BailoutEntry> stack_checks_;
|
ZoneList<BailoutEntry> stack_checks_;
|
||||||
ForwardBailoutStack* forward_bailout_stack_;
|
|
||||||
ForwardBailoutStack* forward_bailout_pending_;
|
|
||||||
|
|
||||||
friend class NestedStatement;
|
friend class NestedStatement;
|
||||||
|
|
||||||
|
@ -5379,7 +5379,7 @@ void HGraphBuilder::VisitNot(UnaryOperation* expr) {
|
|||||||
materialize_true));
|
materialize_true));
|
||||||
|
|
||||||
if (materialize_false->HasPredecessor()) {
|
if (materialize_false->HasPredecessor()) {
|
||||||
materialize_false->SetJoinId(expr->expression()->id());
|
materialize_false->SetJoinId(expr->MaterializeFalseId());
|
||||||
set_current_block(materialize_false);
|
set_current_block(materialize_false);
|
||||||
Push(graph()->GetConstantFalse());
|
Push(graph()->GetConstantFalse());
|
||||||
} else {
|
} else {
|
||||||
@ -5387,7 +5387,7 @@ void HGraphBuilder::VisitNot(UnaryOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (materialize_true->HasPredecessor()) {
|
if (materialize_true->HasPredecessor()) {
|
||||||
materialize_true->SetJoinId(expr->expression()->id());
|
materialize_true->SetJoinId(expr->MaterializeTrueId());
|
||||||
set_current_block(materialize_true);
|
set_current_block(materialize_true);
|
||||||
Push(graph()->GetConstantTrue());
|
Push(graph()->GetConstantTrue());
|
||||||
} else {
|
} else {
|
||||||
|
@ -384,7 +384,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
|
|||||||
void FullCodeGenerator::TestContext::Plug(Variable* var) const {
|
void FullCodeGenerator::TestContext::Plug(Variable* var) const {
|
||||||
// For simplicity we always test the accumulator register.
|
// For simplicity we always test the accumulator register.
|
||||||
codegen()->GetVar(result_register(), var);
|
codegen()->GetVar(result_register(), var);
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +435,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
|
void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
|
codegen()->PrepareForBailoutBeforeSplit(condition(),
|
||||||
true,
|
true,
|
||||||
true_label_,
|
true_label_,
|
||||||
false_label_);
|
false_label_);
|
||||||
@ -494,7 +494,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
|
|||||||
// For simplicity we always test the accumulator register.
|
// For simplicity we always test the accumulator register.
|
||||||
__ Drop(count);
|
__ Drop(count);
|
||||||
__ Move(result_register(), reg);
|
__ Move(result_register(), reg);
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,7 +560,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::TestContext::Plug(bool flag) const {
|
void FullCodeGenerator::TestContext::Plug(bool flag) const {
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
|
codegen()->PrepareForBailoutBeforeSplit(condition(),
|
||||||
true,
|
true,
|
||||||
true_label_,
|
true_label_,
|
||||||
false_label_);
|
false_label_);
|
||||||
@ -653,7 +653,7 @@ void FullCodeGenerator::SetVar(Variable* var,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
|
||||||
bool should_normalize,
|
bool should_normalize,
|
||||||
Label* if_true,
|
Label* if_true,
|
||||||
Label* if_false) {
|
Label* if_false) {
|
||||||
@ -664,13 +664,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
|||||||
|
|
||||||
Label skip;
|
Label skip;
|
||||||
if (should_normalize) __ jmp(&skip, Label::kNear);
|
if (should_normalize) __ jmp(&skip, Label::kNear);
|
||||||
|
PrepareForBailout(expr, TOS_REG);
|
||||||
ForwardBailoutStack* current = forward_bailout_stack_;
|
|
||||||
while (current != NULL) {
|
|
||||||
PrepareForBailout(current->expr(), state);
|
|
||||||
current = current->parent();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (should_normalize) {
|
if (should_normalize) {
|
||||||
__ cmp(eax, isolate()->factory()->true_value());
|
__ cmp(eax, isolate()->factory()->true_value());
|
||||||
Split(equal, if_true, if_false, NULL);
|
Split(equal, if_true, if_false, NULL);
|
||||||
@ -2270,7 +2264,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2282,7 +2277,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
|||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ test(eax, Immediate(kSmiTagMask));
|
__ test(eax, Immediate(kSmiTagMask));
|
||||||
Split(zero, if_true, if_false, fall_through);
|
Split(zero, if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2290,7 +2285,8 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2302,7 +2298,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
|||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ test(eax, Immediate(kSmiTagMask | 0x80000000));
|
__ test(eax, Immediate(kSmiTagMask | 0x80000000));
|
||||||
Split(zero, if_true, if_false, fall_through);
|
Split(zero, if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2310,7 +2306,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2334,14 +2331,15 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
|||||||
__ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
__ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
||||||
__ j(below, if_false);
|
__ j(below, if_false);
|
||||||
__ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
__ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(below_equal, if_true, if_false, fall_through);
|
Split(below_equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2355,14 +2353,15 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(eax, if_false);
|
__ JumpIfSmi(eax, if_false);
|
||||||
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx);
|
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(above_equal, if_true, if_false, fall_through);
|
Split(above_equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2378,7 +2377,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
|||||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||||
__ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
|
__ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
|
||||||
__ test(ebx, Immediate(1 << Map::kIsUndetectable));
|
__ test(ebx, Immediate(1 << Map::kIsUndetectable));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(not_zero, if_true, if_false, fall_through);
|
Split(not_zero, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -2386,7 +2385,8 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
||||||
ZoneList<Expression*>* args) {
|
CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2463,12 +2463,13 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
|||||||
Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
|
Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
|
||||||
__ jmp(if_true);
|
__ jmp(if_true);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2482,14 +2483,15 @@ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(eax, if_false);
|
__ JumpIfSmi(eax, if_false);
|
||||||
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
|
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2503,14 +2505,15 @@ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(eax, if_false);
|
__ JumpIfSmi(eax, if_false);
|
||||||
__ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
|
__ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2524,7 +2527,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(eax, if_false);
|
__ JumpIfSmi(eax, if_false);
|
||||||
__ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
|
__ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -2532,8 +2535,8 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
|
||||||
ASSERT(args->length() == 0);
|
ASSERT(expr->arguments()->length() == 0);
|
||||||
|
|
||||||
Label materialize_true, materialize_false;
|
Label materialize_true, materialize_false;
|
||||||
Label* if_true = NULL;
|
Label* if_true = NULL;
|
||||||
@ -2556,14 +2559,15 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
|
|||||||
__ bind(&check_frame_marker);
|
__ bind(&check_frame_marker);
|
||||||
__ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
|
__ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
|
||||||
Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
|
Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
// Load the two objects into registers and perform the comparison.
|
// Load the two objects into registers and perform the comparison.
|
||||||
@ -2579,14 +2583,15 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ pop(ebx);
|
__ pop(ebx);
|
||||||
__ cmp(eax, ebx);
|
__ cmp(eax, ebx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
// ArgumentsAccessStub expects the key in edx and the formal
|
// ArgumentsAccessStub expects the key in edx and the formal
|
||||||
@ -2600,8 +2605,8 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
|
||||||
ASSERT(args->length() == 0);
|
ASSERT(expr->arguments()->length() == 0);
|
||||||
|
|
||||||
Label exit;
|
Label exit;
|
||||||
// Get the number of formal parameters.
|
// Get the number of formal parameters.
|
||||||
@ -2623,7 +2628,8 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
Label done, null, function, non_function_constructor;
|
Label done, null, function, non_function_constructor;
|
||||||
|
|
||||||
@ -2683,7 +2689,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitLog(CallRuntime* expr) {
|
||||||
// Conditionally generate a log call.
|
// Conditionally generate a log call.
|
||||||
// Args:
|
// Args:
|
||||||
// 0 (literal string): The type of logging (corresponds to the flags).
|
// 0 (literal string): The type of logging (corresponds to the flags).
|
||||||
@ -2691,6 +2697,7 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
|||||||
// 1 (string): Format string. Access the string at argument index 2
|
// 1 (string): Format string. Access the string at argument index 2
|
||||||
// with '%2s' (see Logger::LogRuntime for all the formats).
|
// with '%2s' (see Logger::LogRuntime for all the formats).
|
||||||
// 2 (array): Arguments to the format string.
|
// 2 (array): Arguments to the format string.
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(args->length(), 3);
|
ASSERT_EQ(args->length(), 3);
|
||||||
if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
|
if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2703,8 +2710,8 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
|
||||||
ASSERT(args->length() == 0);
|
ASSERT(expr->arguments()->length() == 0);
|
||||||
|
|
||||||
Label slow_allocate_heapnumber;
|
Label slow_allocate_heapnumber;
|
||||||
Label heapnumber_allocated;
|
Label heapnumber_allocated;
|
||||||
@ -2754,9 +2761,10 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the stub.
|
// Load the arguments on the stack and call the stub.
|
||||||
SubStringStub stub;
|
SubStringStub stub;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 3);
|
ASSERT(args->length() == 3);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2766,9 +2774,10 @@ void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the stub.
|
// Load the arguments on the stack and call the stub.
|
||||||
RegExpExecStub stub;
|
RegExpExecStub stub;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 4);
|
ASSERT(args->length() == 4);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2779,7 +2788,8 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0)); // Load the object.
|
VisitForAccumulatorValue(args->at(0)); // Load the object.
|
||||||
@ -2797,8 +2807,9 @@ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the runtime function.
|
// Load the arguments on the stack and call the runtime function.
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2813,7 +2824,8 @@ void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
VisitForStackValue(args->at(0)); // Load the object.
|
VisitForStackValue(args->at(0)); // Load the object.
|
||||||
@ -2841,7 +2853,8 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(args->length(), 1);
|
ASSERT_EQ(args->length(), 1);
|
||||||
|
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
@ -2853,7 +2866,8 @@ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2871,7 +2885,8 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
@ -2918,7 +2933,8 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
@ -2967,7 +2983,8 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
@ -2979,7 +2996,8 @@ void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
@ -2991,10 +3009,11 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
||||||
TranscendentalCacheStub::TAGGED);
|
TranscendentalCacheStub::TAGGED);
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
@ -3002,10 +3021,11 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
TranscendentalCacheStub stub(TranscendentalCache::COS,
|
TranscendentalCacheStub stub(TranscendentalCache::COS,
|
||||||
TranscendentalCacheStub::TAGGED);
|
TranscendentalCacheStub::TAGGED);
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
@ -3013,10 +3033,11 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
||||||
TranscendentalCacheStub::TAGGED);
|
TranscendentalCacheStub::TAGGED);
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
@ -3024,8 +3045,9 @@ void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the runtime function.
|
// Load the argument on the stack and call the runtime function.
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallRuntime(Runtime::kMath_sqrt, 1);
|
__ CallRuntime(Runtime::kMath_sqrt, 1);
|
||||||
@ -3033,7 +3055,8 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() >= 2);
|
ASSERT(args->length() >= 2);
|
||||||
|
|
||||||
int arg_count = args->length() - 2; // 2 ~ receiver and function.
|
int arg_count = args->length() - 2; // 2 ~ receiver and function.
|
||||||
@ -3052,9 +3075,10 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the stub.
|
// Load the arguments on the stack and call the stub.
|
||||||
RegExpConstructResultStub stub;
|
RegExpConstructResultStub stub;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 3);
|
ASSERT(args->length() == 3);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -3064,7 +3088,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 3);
|
ASSERT(args->length() == 3);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -3156,7 +3181,8 @@ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
ASSERT_NE(NULL, args->at(0)->AsLiteral());
|
ASSERT_NE(NULL, args->at(0)->AsLiteral());
|
||||||
@ -3204,7 +3230,8 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
Register right = eax;
|
Register right = eax;
|
||||||
@ -3241,7 +3268,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -3259,14 +3287,15 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ test(FieldOperand(eax, String::kHashFieldOffset),
|
__ test(FieldOperand(eax, String::kHashFieldOffset),
|
||||||
Immediate(String::kContainsCachedArrayIndexMask));
|
Immediate(String::kContainsCachedArrayIndexMask));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(zero, if_true, if_false, fall_through);
|
Split(zero, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
|
|
||||||
@ -3281,11 +3310,12 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
||||||
Label bailout, done, one_char_separator, long_separator,
|
Label bailout, done, one_char_separator, long_separator,
|
||||||
non_trivial_array, not_size_one_array, loop,
|
non_trivial_array, not_size_one_array, loop,
|
||||||
loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
|
loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
|
||||||
|
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
// We will leave the separator on the stack until the end of the function.
|
// We will leave the separator on the stack until the end of the function.
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -3643,18 +3673,41 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
// Unary NOT has no side effects so it's only necessary to visit the
|
// Unary NOT has no side effects so it's only necessary to visit the
|
||||||
// subexpression. Match the optimizing compiler by not branching.
|
// subexpression. Match the optimizing compiler by not branching.
|
||||||
VisitForEffect(expr->expression());
|
VisitForEffect(expr->expression());
|
||||||
|
} else if (context()->IsTest()) {
|
||||||
|
const TestContext* test = TestContext::cast(context());
|
||||||
|
// The labels are swapped for the recursive call.
|
||||||
|
VisitForControl(expr->expression(),
|
||||||
|
test->false_label(),
|
||||||
|
test->true_label(),
|
||||||
|
test->fall_through());
|
||||||
|
context()->Plug(test->true_label(), test->false_label());
|
||||||
} else {
|
} else {
|
||||||
Label materialize_true, materialize_false;
|
// We handle value contexts explicitly rather than simply visiting
|
||||||
Label* if_true = NULL;
|
// for control and plugging the control flow into the context,
|
||||||
Label* if_false = NULL;
|
// because we need to prepare a pair of extra administrative AST ids
|
||||||
Label* fall_through = NULL;
|
// for the optimizing compiler.
|
||||||
|
ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
|
||||||
// Notice that the labels are swapped.
|
Label materialize_true, materialize_false, done;
|
||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
VisitForControl(expr->expression(),
|
||||||
&if_false, &if_true, &fall_through);
|
&materialize_false,
|
||||||
if (context()->IsTest()) ForwardBailoutToChild(expr);
|
&materialize_true,
|
||||||
VisitForControl(expr->expression(), if_true, if_false, fall_through);
|
&materialize_true);
|
||||||
context()->Plug(if_false, if_true); // Labels swapped.
|
__ bind(&materialize_true);
|
||||||
|
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
|
||||||
|
if (context()->IsAccumulatorValue()) {
|
||||||
|
__ mov(eax, isolate()->factory()->true_value());
|
||||||
|
} else {
|
||||||
|
__ push(isolate()->factory()->true_value());
|
||||||
|
}
|
||||||
|
__ jmp(&done, Label::kNear);
|
||||||
|
__ bind(&materialize_false);
|
||||||
|
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
|
||||||
|
if (context()->IsAccumulatorValue()) {
|
||||||
|
__ mov(eax, isolate()->factory()->false_value());
|
||||||
|
} else {
|
||||||
|
__ push(isolate()->factory()->false_value());
|
||||||
|
}
|
||||||
|
__ bind(&done);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3925,12 +3978,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|||||||
context()->Plug(eax);
|
context()->Plug(eax);
|
||||||
} else {
|
} else {
|
||||||
// This expression cannot throw a reference error at the top level.
|
// This expression cannot throw a reference error at the top level.
|
||||||
VisitInCurrentContext(expr);
|
VisitInDuplicateContext(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
Label materialize_true, materialize_false;
|
Label materialize_true, materialize_false;
|
||||||
Label* if_true = NULL;
|
Label* if_true = NULL;
|
||||||
@ -3940,9 +3994,9 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
|||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
{ AccumulatorValueContext context(this);
|
{ AccumulatorValueContext context(this);
|
||||||
VisitForTypeofValue(expr);
|
VisitForTypeofValue(sub_expr);
|
||||||
}
|
}
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
|
|
||||||
if (check->Equals(isolate()->heap()->number_symbol())) {
|
if (check->Equals(isolate()->heap()->number_symbol())) {
|
||||||
__ JumpIfSmi(eax, if_true);
|
__ JumpIfSmi(eax, if_true);
|
||||||
@ -4026,7 +4080,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
case Token::IN:
|
case Token::IN:
|
||||||
VisitForStackValue(expr->right());
|
VisitForStackValue(expr->right());
|
||||||
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
|
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
|
||||||
__ cmp(eax, isolate()->factory()->true_value());
|
__ cmp(eax, isolate()->factory()->true_value());
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
break;
|
break;
|
||||||
@ -4035,7 +4089,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
VisitForStackValue(expr->right());
|
VisitForStackValue(expr->right());
|
||||||
InstanceofStub stub(InstanceofStub::kNoFlags);
|
InstanceofStub stub(InstanceofStub::kNoFlags);
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ test(eax, eax);
|
__ test(eax, eax);
|
||||||
// The stub returns 0 for true.
|
// The stub returns 0 for true.
|
||||||
Split(zero, if_true, if_false, fall_through);
|
Split(zero, if_true, if_false, fall_through);
|
||||||
@ -4087,7 +4141,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
__ call(ic, RelocInfo::CODE_TARGET, expr->id());
|
__ call(ic, RelocInfo::CODE_TARGET, expr->id());
|
||||||
patch_site.EmitPatchInfo();
|
patch_site.EmitPatchInfo();
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ test(eax, eax);
|
__ test(eax, eax);
|
||||||
Split(cc, if_true, if_false, fall_through);
|
Split(cc, if_true, if_false, fall_through);
|
||||||
}
|
}
|
||||||
@ -4110,7 +4164,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
|
|||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
VisitForAccumulatorValue(sub_expr);
|
VisitForAccumulatorValue(sub_expr);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Handle<Object> nil_value = nil == kNullValue ?
|
Handle<Object> nil_value = nil == kNullValue ?
|
||||||
isolate()->factory()->null_value() :
|
isolate()->factory()->null_value() :
|
||||||
isolate()->factory()->undefined_value();
|
isolate()->factory()->undefined_value();
|
||||||
|
@ -405,7 +405,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
|
|||||||
void FullCodeGenerator::TestContext::Plug(Variable* var) const {
|
void FullCodeGenerator::TestContext::Plug(Variable* var) const {
|
||||||
// For simplicity we always test the accumulator register.
|
// For simplicity we always test the accumulator register.
|
||||||
codegen()->GetVar(result_register(), var);
|
codegen()->GetVar(result_register(), var);
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,7 +522,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
|
|||||||
// For simplicity we always test the accumulator register.
|
// For simplicity we always test the accumulator register.
|
||||||
__ Drop(count);
|
__ Drop(count);
|
||||||
__ Move(result_register(), reg);
|
__ Move(result_register(), reg);
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2413,7 +2413,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
|||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
__ And(t0, v0, Operand(kSmiTagMask));
|
__ And(t0, v0, Operand(kSmiTagMask));
|
||||||
Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through);
|
Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2433,7 +2433,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
|||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
__ And(at, v0, Operand(kSmiTagMask | 0x80000000));
|
__ And(at, v0, Operand(kSmiTagMask | 0x80000000));
|
||||||
Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through);
|
Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2463,7 +2463,7 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
|||||||
__ Branch(if_false, ne, at, Operand(zero_reg));
|
__ Branch(if_false, ne, at, Operand(zero_reg));
|
||||||
__ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
|
__ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
|
||||||
__ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
__ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE),
|
Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE),
|
||||||
if_true, if_false, fall_through);
|
if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2485,7 +2485,7 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(v0, if_false);
|
__ JumpIfSmi(v0, if_false);
|
||||||
__ GetObjectType(v0, a1, a1);
|
__ GetObjectType(v0, a1, a1);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE),
|
Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE),
|
||||||
if_true, if_false, fall_through);
|
if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2509,7 +2509,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
|||||||
__ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
|
__ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
|
||||||
__ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset));
|
__ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset));
|
||||||
__ And(at, a1, Operand(1 << Map::kIsUndetectable));
|
__ And(at, a1, Operand(1 << Map::kIsUndetectable));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through);
|
Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -2594,7 +2594,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
|||||||
__ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset));
|
__ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset));
|
||||||
__ jmp(if_true);
|
__ jmp(if_true);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2613,7 +2613,7 @@ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(v0, if_false);
|
__ JumpIfSmi(v0, if_false);
|
||||||
__ GetObjectType(v0, a1, a2);
|
__ GetObjectType(v0, a1, a2);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
__ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE));
|
__ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE));
|
||||||
__ Branch(if_false);
|
__ Branch(if_false);
|
||||||
|
|
||||||
@ -2635,7 +2635,7 @@ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(v0, if_false);
|
__ JumpIfSmi(v0, if_false);
|
||||||
__ GetObjectType(v0, a1, a1);
|
__ GetObjectType(v0, a1, a1);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Split(eq, a1, Operand(JS_ARRAY_TYPE),
|
Split(eq, a1, Operand(JS_ARRAY_TYPE),
|
||||||
if_true, if_false, fall_through);
|
if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2657,7 +2657,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(v0, if_false);
|
__ JumpIfSmi(v0, if_false);
|
||||||
__ GetObjectType(v0, a1, a1);
|
__ GetObjectType(v0, a1, a1);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through);
|
Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -2687,7 +2687,7 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
|
|||||||
// Check the marker in the calling frame.
|
// Check the marker in the calling frame.
|
||||||
__ bind(&check_frame_marker);
|
__ bind(&check_frame_marker);
|
||||||
__ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset));
|
__ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)),
|
Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)),
|
||||||
if_true, if_false, fall_through);
|
if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2710,7 +2710,7 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
|
|||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
__ pop(a1);
|
__ pop(a1);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Split(eq, v0, Operand(a1), if_true, if_false, fall_through);
|
Split(eq, v0, Operand(a1), if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -3396,7 +3396,7 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
|
|||||||
__ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset));
|
__ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset));
|
||||||
__ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask));
|
__ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask));
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through);
|
Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -4048,7 +4048,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
|||||||
{ AccumulatorValueContext context(this);
|
{ AccumulatorValueContext context(this);
|
||||||
VisitForTypeofValue(expr);
|
VisitForTypeofValue(expr);
|
||||||
}
|
}
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
|
|
||||||
if (check->Equals(isolate()->heap()->number_symbol())) {
|
if (check->Equals(isolate()->heap()->number_symbol())) {
|
||||||
__ JumpIfSmi(v0, if_true);
|
__ JumpIfSmi(v0, if_true);
|
||||||
@ -4134,7 +4134,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
case Token::IN:
|
case Token::IN:
|
||||||
VisitForStackValue(expr->right());
|
VisitForStackValue(expr->right());
|
||||||
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
|
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
PrepareForBailoutBeforeSplit(false, NULL, NULL);
|
||||||
__ LoadRoot(t0, Heap::kTrueValueRootIndex);
|
__ LoadRoot(t0, Heap::kTrueValueRootIndex);
|
||||||
Split(eq, v0, Operand(t0), if_true, if_false, fall_through);
|
Split(eq, v0, Operand(t0), if_true, if_false, fall_through);
|
||||||
break;
|
break;
|
||||||
@ -4143,7 +4143,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
VisitForStackValue(expr->right());
|
VisitForStackValue(expr->right());
|
||||||
InstanceofStub stub(InstanceofStub::kNoFlags);
|
InstanceofStub stub(InstanceofStub::kNoFlags);
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
// The stub returns 0 for true.
|
// The stub returns 0 for true.
|
||||||
Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through);
|
Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through);
|
||||||
break;
|
break;
|
||||||
@ -4191,7 +4191,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
Handle<Code> ic = CompareIC::GetUninitialized(op);
|
Handle<Code> ic = CompareIC::GetUninitialized(op);
|
||||||
__ Call(ic, RelocInfo::CODE_TARGET, expr->id());
|
__ Call(ic, RelocInfo::CODE_TARGET, expr->id());
|
||||||
patch_site.EmitPatchInfo();
|
patch_site.EmitPatchInfo();
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
|
Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4213,7 +4213,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
|
|||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
VisitForAccumulatorValue(sub_expr);
|
VisitForAccumulatorValue(sub_expr);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(true, if_true, if_false);
|
||||||
Heap::RootListIndex nil_value = nil == kNullValue ?
|
Heap::RootListIndex nil_value = nil == kNullValue ?
|
||||||
Heap::kNullValueRootIndex :
|
Heap::kNullValueRootIndex :
|
||||||
Heap::kUndefinedValueRootIndex;
|
Heap::kUndefinedValueRootIndex;
|
||||||
|
@ -378,7 +378,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
|
|||||||
|
|
||||||
void FullCodeGenerator::TestContext::Plug(Variable* var) const {
|
void FullCodeGenerator::TestContext::Plug(Variable* var) const {
|
||||||
codegen()->GetVar(result_register(), var);
|
codegen()->GetVar(result_register(), var);
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,7 +400,7 @@ void FullCodeGenerator::StackValueContext::Plug(
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
|
void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
|
codegen()->PrepareForBailoutBeforeSplit(condition(),
|
||||||
true,
|
true,
|
||||||
true_label_,
|
true_label_,
|
||||||
false_label_);
|
false_label_);
|
||||||
@ -433,7 +433,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
|
void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
|
codegen()->PrepareForBailoutBeforeSplit(condition(),
|
||||||
true,
|
true,
|
||||||
true_label_,
|
true_label_,
|
||||||
false_label_);
|
false_label_);
|
||||||
@ -492,7 +492,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
|
|||||||
// For simplicity we always test the accumulator register.
|
// For simplicity we always test the accumulator register.
|
||||||
__ Drop(count);
|
__ Drop(count);
|
||||||
__ Move(result_register(), reg);
|
__ Move(result_register(), reg);
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
|
||||||
codegen()->DoTest(this);
|
codegen()->DoTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,7 +556,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::TestContext::Plug(bool flag) const {
|
void FullCodeGenerator::TestContext::Plug(bool flag) const {
|
||||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
|
codegen()->PrepareForBailoutBeforeSplit(condition(),
|
||||||
true,
|
true,
|
||||||
true_label_,
|
true_label_,
|
||||||
false_label_);
|
false_label_);
|
||||||
@ -648,7 +648,7 @@ void FullCodeGenerator::SetVar(Variable* var,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
|
||||||
bool should_normalize,
|
bool should_normalize,
|
||||||
Label* if_true,
|
Label* if_true,
|
||||||
Label* if_false) {
|
Label* if_false) {
|
||||||
@ -659,13 +659,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
|||||||
|
|
||||||
Label skip;
|
Label skip;
|
||||||
if (should_normalize) __ jmp(&skip, Label::kNear);
|
if (should_normalize) __ jmp(&skip, Label::kNear);
|
||||||
|
PrepareForBailout(expr, TOS_REG);
|
||||||
ForwardBailoutStack* current = forward_bailout_stack_;
|
|
||||||
while (current != NULL) {
|
|
||||||
PrepareForBailout(current->expr(), state);
|
|
||||||
current = current->parent();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (should_normalize) {
|
if (should_normalize) {
|
||||||
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
|
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
|
||||||
Split(equal, if_true, if_false, NULL);
|
Split(equal, if_true, if_false, NULL);
|
||||||
@ -2264,7 +2258,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2276,7 +2271,7 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
|||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ JumpIfSmi(rax, if_true);
|
__ JumpIfSmi(rax, if_true);
|
||||||
__ jmp(if_false);
|
__ jmp(if_false);
|
||||||
|
|
||||||
@ -2284,7 +2279,8 @@ void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2296,7 +2292,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
|||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
|
Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
|
||||||
Split(non_negative_smi, if_true, if_false, fall_through);
|
Split(non_negative_smi, if_true, if_false, fall_through);
|
||||||
|
|
||||||
@ -2304,7 +2300,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2328,14 +2325,15 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
|||||||
__ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
__ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
||||||
__ j(below, if_false);
|
__ j(below, if_false);
|
||||||
__ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
__ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(below_equal, if_true, if_false, fall_through);
|
Split(below_equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2349,14 +2347,15 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(rax, if_false);
|
__ JumpIfSmi(rax, if_false);
|
||||||
__ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
|
__ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(above_equal, if_true, if_false, fall_through);
|
Split(above_equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2372,7 +2371,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
|||||||
__ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
|
__ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
|
||||||
__ testb(FieldOperand(rbx, Map::kBitFieldOffset),
|
__ testb(FieldOperand(rbx, Map::kBitFieldOffset),
|
||||||
Immediate(1 << Map::kIsUndetectable));
|
Immediate(1 << Map::kIsUndetectable));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(not_zero, if_true, if_false, fall_through);
|
Split(not_zero, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -2380,7 +2379,8 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
||||||
ZoneList<Expression*>* args) {
|
CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2456,12 +2456,13 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
|||||||
Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
|
Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
|
||||||
__ jmp(if_true);
|
__ jmp(if_true);
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2475,14 +2476,15 @@ void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(rax, if_false);
|
__ JumpIfSmi(rax, if_false);
|
||||||
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
|
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2496,14 +2498,15 @@ void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(rax, if_false);
|
__ JumpIfSmi(rax, if_false);
|
||||||
__ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
|
__ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2517,7 +2520,7 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ JumpIfSmi(rax, if_false);
|
__ JumpIfSmi(rax, if_false);
|
||||||
__ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
|
__ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
@ -2525,8 +2528,8 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
|
||||||
ASSERT(args->length() == 0);
|
ASSERT(expr->arguments()->length() == 0);
|
||||||
|
|
||||||
Label materialize_true, materialize_false;
|
Label materialize_true, materialize_false;
|
||||||
Label* if_true = NULL;
|
Label* if_true = NULL;
|
||||||
@ -2549,14 +2552,15 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
|
|||||||
__ bind(&check_frame_marker);
|
__ bind(&check_frame_marker);
|
||||||
__ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
|
__ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
|
||||||
Smi::FromInt(StackFrame::CONSTRUCT));
|
Smi::FromInt(StackFrame::CONSTRUCT));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
// Load the two objects into registers and perform the comparison.
|
// Load the two objects into registers and perform the comparison.
|
||||||
@ -2572,14 +2576,15 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ pop(rbx);
|
__ pop(rbx);
|
||||||
__ cmpq(rax, rbx);
|
__ cmpq(rax, rbx);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
|
|
||||||
context()->Plug(if_true, if_false);
|
context()->Plug(if_true, if_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
// ArgumentsAccessStub expects the key in rdx and the formal
|
// ArgumentsAccessStub expects the key in rdx and the formal
|
||||||
@ -2593,8 +2598,8 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
|
||||||
ASSERT(args->length() == 0);
|
ASSERT(expr->arguments()->length() == 0);
|
||||||
|
|
||||||
Label exit;
|
Label exit;
|
||||||
// Get the number of formal parameters.
|
// Get the number of formal parameters.
|
||||||
@ -2616,7 +2621,8 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
Label done, null, function, non_function_constructor;
|
Label done, null, function, non_function_constructor;
|
||||||
|
|
||||||
@ -2676,7 +2682,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitLog(CallRuntime* expr) {
|
||||||
// Conditionally generate a log call.
|
// Conditionally generate a log call.
|
||||||
// Args:
|
// Args:
|
||||||
// 0 (literal string): The type of logging (corresponds to the flags).
|
// 0 (literal string): The type of logging (corresponds to the flags).
|
||||||
@ -2684,6 +2690,7 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
|||||||
// 1 (string): Format string. Access the string at argument index 2
|
// 1 (string): Format string. Access the string at argument index 2
|
||||||
// with '%2s' (see Logger::LogRuntime for all the formats).
|
// with '%2s' (see Logger::LogRuntime for all the formats).
|
||||||
// 2 (array): Arguments to the format string.
|
// 2 (array): Arguments to the format string.
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(args->length(), 3);
|
ASSERT_EQ(args->length(), 3);
|
||||||
if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
|
if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2696,8 +2703,8 @@ void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
|
||||||
ASSERT(args->length() == 0);
|
ASSERT(expr->arguments()->length() == 0);
|
||||||
|
|
||||||
Label slow_allocate_heapnumber;
|
Label slow_allocate_heapnumber;
|
||||||
Label heapnumber_allocated;
|
Label heapnumber_allocated;
|
||||||
@ -2741,9 +2748,10 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the stub.
|
// Load the arguments on the stack and call the stub.
|
||||||
SubStringStub stub;
|
SubStringStub stub;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 3);
|
ASSERT(args->length() == 3);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2753,9 +2761,10 @@ void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the stub.
|
// Load the arguments on the stack and call the stub.
|
||||||
RegExpExecStub stub;
|
RegExpExecStub stub;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 4);
|
ASSERT(args->length() == 4);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2766,7 +2775,8 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0)); // Load the object.
|
VisitForAccumulatorValue(args->at(0)); // Load the object.
|
||||||
@ -2784,8 +2794,9 @@ void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
|
||||||
// Load the arguments on the stack and call the runtime function.
|
// Load the arguments on the stack and call the runtime function.
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -2795,7 +2806,8 @@ void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
VisitForStackValue(args->at(0)); // Load the object.
|
VisitForStackValue(args->at(0)); // Load the object.
|
||||||
@ -2822,7 +2834,8 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(args->length(), 1);
|
ASSERT_EQ(args->length(), 1);
|
||||||
|
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
@ -2834,7 +2847,8 @@ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -2852,7 +2866,8 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
@ -2899,7 +2914,8 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
@ -2948,7 +2964,8 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
@ -2960,7 +2977,8 @@ void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
@ -2972,10 +2990,11 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
||||||
TranscendentalCacheStub::TAGGED);
|
TranscendentalCacheStub::TAGGED);
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
@ -2983,10 +3002,11 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
TranscendentalCacheStub stub(TranscendentalCache::COS,
|
TranscendentalCacheStub stub(TranscendentalCache::COS,
|
||||||
TranscendentalCacheStub::TAGGED);
|
TranscendentalCacheStub::TAGGED);
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
@ -2994,10 +3014,11 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the stub.
|
// Load the argument on the stack and call the stub.
|
||||||
TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
||||||
TranscendentalCacheStub::TAGGED);
|
TranscendentalCacheStub::TAGGED);
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
@ -3005,8 +3026,9 @@ void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
|
||||||
// Load the argument on the stack and call the runtime function.
|
// Load the argument on the stack and call the runtime function.
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
__ CallRuntime(Runtime::kMath_sqrt, 1);
|
__ CallRuntime(Runtime::kMath_sqrt, 1);
|
||||||
@ -3014,7 +3036,8 @@ void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() >= 2);
|
ASSERT(args->length() >= 2);
|
||||||
|
|
||||||
int arg_count = args->length() - 2; // 2 ~ receiver and function.
|
int arg_count = args->length() - 2; // 2 ~ receiver and function.
|
||||||
@ -3033,8 +3056,9 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
|
||||||
RegExpConstructResultStub stub;
|
RegExpConstructResultStub stub;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 3);
|
ASSERT(args->length() == 3);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -3044,7 +3068,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 3);
|
ASSERT(args->length() == 3);
|
||||||
VisitForStackValue(args->at(0));
|
VisitForStackValue(args->at(0));
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -3139,7 +3164,8 @@ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
ASSERT_NE(NULL, args->at(0)->AsLiteral());
|
ASSERT_NE(NULL, args->at(0)->AsLiteral());
|
||||||
@ -3195,7 +3221,8 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT_EQ(2, args->length());
|
ASSERT_EQ(2, args->length());
|
||||||
|
|
||||||
Register right = rax;
|
Register right = rax;
|
||||||
@ -3233,7 +3260,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
|
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
@ -3247,7 +3275,7 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
|
|||||||
|
|
||||||
__ testl(FieldOperand(rax, String::kHashFieldOffset),
|
__ testl(FieldOperand(rax, String::kHashFieldOffset),
|
||||||
Immediate(String::kContainsCachedArrayIndexMask));
|
Immediate(String::kContainsCachedArrayIndexMask));
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ j(zero, if_true);
|
__ j(zero, if_true);
|
||||||
__ jmp(if_false);
|
__ jmp(if_false);
|
||||||
|
|
||||||
@ -3255,7 +3283,8 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
VisitForAccumulatorValue(args->at(0));
|
VisitForAccumulatorValue(args->at(0));
|
||||||
|
|
||||||
@ -3271,10 +3300,11 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
|
void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
||||||
Label bailout, return_result, done, one_char_separator, long_separator,
|
Label bailout, return_result, done, one_char_separator, long_separator,
|
||||||
non_trivial_array, not_size_one_array, loop,
|
non_trivial_array, not_size_one_array, loop,
|
||||||
loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
|
loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
|
||||||
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
ASSERT(args->length() == 2);
|
ASSERT(args->length() == 2);
|
||||||
// We will leave the separator on the stack until the end of the function.
|
// We will leave the separator on the stack until the end of the function.
|
||||||
VisitForStackValue(args->at(1));
|
VisitForStackValue(args->at(1));
|
||||||
@ -3653,17 +3683,41 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
// Unary NOT has no side effects so it's only necessary to visit the
|
// Unary NOT has no side effects so it's only necessary to visit the
|
||||||
// subexpression. Match the optimizing compiler by not branching.
|
// subexpression. Match the optimizing compiler by not branching.
|
||||||
VisitForEffect(expr->expression());
|
VisitForEffect(expr->expression());
|
||||||
|
} else if (context()->IsTest()) {
|
||||||
|
const TestContext* test = TestContext::cast(context());
|
||||||
|
// The labels are swapped for the recursive call.
|
||||||
|
VisitForControl(expr->expression(),
|
||||||
|
test->false_label(),
|
||||||
|
test->true_label(),
|
||||||
|
test->fall_through());
|
||||||
|
context()->Plug(test->true_label(), test->false_label());
|
||||||
} else {
|
} else {
|
||||||
Label materialize_true, materialize_false;
|
// We handle value contexts explicitly rather than simply visiting
|
||||||
Label* if_true = NULL;
|
// for control and plugging the control flow into the context,
|
||||||
Label* if_false = NULL;
|
// because we need to prepare a pair of extra administrative AST ids
|
||||||
Label* fall_through = NULL;
|
// for the optimizing compiler.
|
||||||
// Notice that the labels are swapped.
|
ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
|
||||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
Label materialize_true, materialize_false, done;
|
||||||
&if_false, &if_true, &fall_through);
|
VisitForControl(expr->expression(),
|
||||||
if (context()->IsTest()) ForwardBailoutToChild(expr);
|
&materialize_false,
|
||||||
VisitForControl(expr->expression(), if_true, if_false, fall_through);
|
&materialize_true,
|
||||||
context()->Plug(if_false, if_true); // Labels swapped.
|
&materialize_true);
|
||||||
|
__ bind(&materialize_true);
|
||||||
|
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
|
||||||
|
if (context()->IsAccumulatorValue()) {
|
||||||
|
__ LoadRoot(rax, Heap::kTrueValueRootIndex);
|
||||||
|
} else {
|
||||||
|
__ PushRoot(Heap::kTrueValueRootIndex);
|
||||||
|
}
|
||||||
|
__ jmp(&done, Label::kNear);
|
||||||
|
__ bind(&materialize_false);
|
||||||
|
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
|
||||||
|
if (context()->IsAccumulatorValue()) {
|
||||||
|
__ LoadRoot(rax, Heap::kFalseValueRootIndex);
|
||||||
|
} else {
|
||||||
|
__ PushRoot(Heap::kFalseValueRootIndex);
|
||||||
|
}
|
||||||
|
__ bind(&done);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3935,12 +3989,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|||||||
context()->Plug(rax);
|
context()->Plug(rax);
|
||||||
} else {
|
} else {
|
||||||
// This expression cannot throw a reference error at the top level.
|
// This expression cannot throw a reference error at the top level.
|
||||||
VisitInCurrentContext(expr);
|
VisitInDuplicateContext(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
Label materialize_true, materialize_false;
|
Label materialize_true, materialize_false;
|
||||||
Label* if_true = NULL;
|
Label* if_true = NULL;
|
||||||
@ -3950,9 +4005,9 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
|||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
{ AccumulatorValueContext context(this);
|
{ AccumulatorValueContext context(this);
|
||||||
VisitForTypeofValue(expr);
|
VisitForTypeofValue(sub_expr);
|
||||||
}
|
}
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
|
|
||||||
if (check->Equals(isolate()->heap()->number_symbol())) {
|
if (check->Equals(isolate()->heap()->number_symbol())) {
|
||||||
__ JumpIfSmi(rax, if_true);
|
__ JumpIfSmi(rax, if_true);
|
||||||
@ -4036,7 +4091,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
case Token::IN:
|
case Token::IN:
|
||||||
VisitForStackValue(expr->right());
|
VisitForStackValue(expr->right());
|
||||||
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
|
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
|
||||||
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
|
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
|
||||||
Split(equal, if_true, if_false, fall_through);
|
Split(equal, if_true, if_false, fall_through);
|
||||||
break;
|
break;
|
||||||
@ -4045,7 +4100,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
VisitForStackValue(expr->right());
|
VisitForStackValue(expr->right());
|
||||||
InstanceofStub stub(InstanceofStub::kNoFlags);
|
InstanceofStub stub(InstanceofStub::kNoFlags);
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ testq(rax, rax);
|
__ testq(rax, rax);
|
||||||
// The stub returns 0 for true.
|
// The stub returns 0 for true.
|
||||||
Split(zero, if_true, if_false, fall_through);
|
Split(zero, if_true, if_false, fall_through);
|
||||||
@ -4097,7 +4152,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
__ call(ic, RelocInfo::CODE_TARGET, expr->id());
|
__ call(ic, RelocInfo::CODE_TARGET, expr->id());
|
||||||
patch_site.EmitPatchInfo();
|
patch_site.EmitPatchInfo();
|
||||||
|
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
__ testq(rax, rax);
|
__ testq(rax, rax);
|
||||||
Split(cc, if_true, if_false, fall_through);
|
Split(cc, if_true, if_false, fall_through);
|
||||||
}
|
}
|
||||||
@ -4120,7 +4175,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
|
|||||||
&if_true, &if_false, &fall_through);
|
&if_true, &if_false, &fall_through);
|
||||||
|
|
||||||
VisitForAccumulatorValue(sub_expr);
|
VisitForAccumulatorValue(sub_expr);
|
||||||
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||||
Heap::RootListIndex nil_value = nil == kNullValue ?
|
Heap::RootListIndex nil_value = nil == kNullValue ?
|
||||||
Heap::kNullValueRootIndex :
|
Heap::kNullValueRootIndex :
|
||||||
Heap::kUndefinedValueRootIndex;
|
Heap::kUndefinedValueRootIndex;
|
||||||
|
Loading…
Reference in New Issue
Block a user