Index: src/ia32/full-codegen-ia32.cc |
=================================================================== |
--- src/ia32/full-codegen-ia32.cc (revision 5450) |
+++ src/ia32/full-codegen-ia32.cc (working copy) |
@@ -239,226 +239,165 @@ |
} |
-void FullCodeGenerator::Apply(Expression::Context context, Register reg) { |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
+void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { |
+ // Nothing to do. |
+} |
- case Expression::kEffect: |
- // Nothing to do. |
- break; |
- case Expression::kValue: |
- // Move value into place. |
- switch (location_) { |
- case kAccumulator: |
- if (!reg.is(result_register())) __ mov(result_register(), reg); |
- break; |
- case kStack: |
- __ push(reg); |
- break; |
- } |
- break; |
+void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { |
+ MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); |
+ __ mov(result_register(), slot_operand); |
+} |
- case Expression::kTest: |
- // For simplicity we always test the accumulator register. |
- if (!reg.is(result_register())) __ mov(result_register(), reg); |
- DoTest(true_label_, false_label_, fall_through_); |
- break; |
- } |
+ |
+void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { |
+ MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); |
+ // Memory operands can be pushed directly. |
+ __ push(slot_operand); |
} |
-void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- case Expression::kEffect: |
- // Nothing to do. |
- break; |
- case Expression::kValue: { |
- MemOperand slot_operand = EmitSlotSearch(slot, result_register()); |
- switch (location_) { |
- case kAccumulator: |
- __ mov(result_register(), slot_operand); |
- break; |
- case kStack: |
- // Memory operands can be pushed directly. |
- __ push(slot_operand); |
- break; |
- } |
- break; |
- } |
+void FullCodeGenerator::TestContext::Plug(Slot* slot) const { |
+ // For simplicity we always test the accumulator register. |
+ codegen()->Move(result_register(), slot); |
+ codegen()->DoTest(true_label_, false_label_, fall_through_); |
+} |
- case Expression::kTest: |
- // For simplicity we always test the accumulator register. |
- Move(result_register(), slot); |
- DoTest(true_label_, false_label_, fall_through_); |
- break; |
- } |
+ |
+void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
+ UNREACHABLE(); // Not used on IA32. |
} |
-void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- case Expression::kEffect: |
- // Nothing to do. |
- break; |
- case Expression::kValue: |
- switch (location_) { |
- case kAccumulator: |
- __ mov(result_register(), lit->handle()); |
- break; |
- case kStack: |
- // Immediates can be pushed directly. |
- __ push(Immediate(lit->handle())); |
- break; |
- } |
- break; |
+void FullCodeGenerator::AccumulatorValueContext::Plug( |
+ Heap::RootListIndex index) const { |
+ UNREACHABLE(); // Not used on IA32. |
+} |
- case Expression::kTest: |
- // For simplicity we always test the accumulator register. |
- __ mov(result_register(), lit->handle()); |
- DoTest(true_label_, false_label_, fall_through_); |
- break; |
- } |
+ |
+void FullCodeGenerator::StackValueContext::Plug( |
+ Heap::RootListIndex index) const { |
+ UNREACHABLE(); // Not used on IA32. |
} |
-void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
+void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { |
+ UNREACHABLE(); // Not used on IA32. |
+} |
- case Expression::kEffect: |
- __ Drop(1); |
- break; |
- case Expression::kValue: |
- switch (location_) { |
- case kAccumulator: |
- __ pop(result_register()); |
- break; |
- case kStack: |
- break; |
- } |
- break; |
+void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { |
+ // Nothing to do. |
+} |
- case Expression::kTest: |
- // For simplicity we always test the accumulator register. |
- __ pop(result_register()); |
- DoTest(true_label_, false_label_, fall_through_); |
- break; |
+ |
+void FullCodeGenerator::AccumulatorValueContext::Plug( |
+ Handle<Object> lit) const { |
+ __ mov(result_register(), lit); |
+} |
+ |
+ |
+void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
+ // Immediates can be pushed directly. |
+ __ push(Immediate(lit)); |
+} |
+ |
+ |
+void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
+ ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. |
+ if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
+ __ jmp(false_label_); |
+ } else if (lit->IsTrue() || lit->IsJSObject()) { |
+ __ jmp(true_label_); |
+ } else if (lit->IsString()) { |
+ if (String::cast(*lit)->length() == 0) { |
+ __ jmp(false_label_); |
+ } else { |
+ __ jmp(true_label_); |
+ } |
+ } else if (lit->IsSmi()) { |
+ if (Smi::cast(*lit)->value() == 0) { |
+ __ jmp(false_label_); |
+ } else { |
+ __ jmp(true_label_); |
+ } |
+ } else { |
+ // For simplicity we always test the accumulator register. |
+ __ mov(result_register(), lit); |
+ codegen()->DoTest(true_label_, false_label_, fall_through_); |
} |
} |
-void FullCodeGenerator::DropAndApply(int count, |
- Expression::Context context, |
- Register reg) { |
+void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
+ Register reg) const { |
ASSERT(count > 0); |
- ASSERT(!reg.is(esp)); |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
+ if (count > 1) __ Drop(count - 1); |
+ __ mov(Operand(esp, 0), reg); |
+} |
- case Expression::kEffect: |
- __ Drop(count); |
- break; |
- case Expression::kValue: |
- switch (location_) { |
- case kAccumulator: |
- __ Drop(count); |
- if (!reg.is(result_register())) __ mov(result_register(), reg); |
- break; |
- case kStack: |
- if (count > 1) __ Drop(count - 1); |
- __ mov(Operand(esp, 0), reg); |
- break; |
- } |
- break; |
+void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
+ Label* materialize_false) const { |
+ ASSERT_EQ(materialize_true, materialize_false); |
+ __ bind(materialize_true); |
+} |
- case Expression::kTest: |
- // For simplicity we always test the accumulator register. |
- __ Drop(count); |
- if (!reg.is(result_register())) __ mov(result_register(), reg); |
- DoTest(true_label_, false_label_, fall_through_); |
- break; |
- } |
+ |
+void FullCodeGenerator::AccumulatorValueContext::Plug( |
+ Label* materialize_true, |
+ Label* materialize_false) const { |
+ Label done; |
+ __ bind(materialize_true); |
+ __ mov(result_register(), Factory::true_value()); |
+ __ jmp(&done); |
+ __ bind(materialize_false); |
+ __ mov(result_register(), Factory::false_value()); |
+ __ bind(&done); |
} |
-void FullCodeGenerator::Apply(Expression::Context context, |
- Label* materialize_true, |
- Label* materialize_false) { |
- switch (context) { |
- case Expression::kUninitialized: |
+void FullCodeGenerator::StackValueContext::Plug( |
+ Label* materialize_true, |
+ Label* materialize_false) const { |
+ Label done; |
+ __ bind(materialize_true); |
+ __ push(Immediate(Factory::true_value())); |
+ __ jmp(&done); |
+ __ bind(materialize_false); |
+ __ push(Immediate(Factory::false_value())); |
+ __ bind(&done); |
+} |
- case Expression::kEffect: |
- ASSERT_EQ(materialize_true, materialize_false); |
- __ bind(materialize_true); |
- break; |
- case Expression::kValue: { |
- Label done; |
- switch (location_) { |
- case kAccumulator: |
- __ bind(materialize_true); |
- __ mov(result_register(), Factory::true_value()); |
- __ jmp(&done); |
- __ bind(materialize_false); |
- __ mov(result_register(), Factory::false_value()); |
- break; |
- case kStack: |
- __ bind(materialize_true); |
- __ push(Immediate(Factory::true_value())); |
- __ jmp(&done); |
- __ bind(materialize_false); |
- __ push(Immediate(Factory::false_value())); |
- break; |
- } |
- __ bind(&done); |
- break; |
- } |
+void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
+ Label* materialize_false) const { |
+} |
- case Expression::kTest: |
- break; |
- } |
+ |
+void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
} |
-// Convert constant control flow (true or false) to the result expected for |
-// a given expression context. |
-void FullCodeGenerator::Apply(Expression::Context context, bool flag) { |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- break; |
- case Expression::kEffect: |
- break; |
- case Expression::kValue: { |
- Handle<Object> value = |
- flag ? Factory::true_value() : Factory::false_value(); |
- switch (location_) { |
- case kAccumulator: |
- __ mov(result_register(), value); |
- break; |
- case kStack: |
- __ push(Immediate(value)); |
- break; |
- } |
- break; |
- } |
- case Expression::kTest: |
- if (flag) { |
- if (true_label_ != fall_through_) __ jmp(true_label_); |
- } else { |
- if (false_label_ != fall_through_) __ jmp(false_label_); |
- } |
- break; |
+void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
+ Handle<Object> value = |
+ flag ? Factory::true_value() : Factory::false_value(); |
+ __ mov(result_register(), value); |
+} |
+ |
+ |
+void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
+ Handle<Object> value = |
+ flag ? Factory::true_value() : Factory::false_value(); |
+ __ push(Immediate(value)); |
+} |
+ |
+ |
+void FullCodeGenerator::TestContext::Plug(bool flag) const { |
+ if (flag) { |
+ if (true_label_ != fall_through_) __ jmp(true_label_); |
+ } else { |
+ if (false_label_ != fall_through_) __ jmp(false_label_); |
} |
} |
@@ -561,7 +500,7 @@ |
__ mov(Operand(ebp, SlotOffset(slot)), |
Immediate(Factory::the_hole_value())); |
} else if (function != NULL) { |
- VisitForValue(function, kAccumulator); |
+ VisitForAccumulatorValue(function); |
__ mov(Operand(ebp, SlotOffset(slot)), result_register()); |
} |
break; |
@@ -583,7 +522,7 @@ |
Immediate(Factory::the_hole_value())); |
// No write barrier since the hole value is in old space. |
} else if (function != NULL) { |
- VisitForValue(function, kAccumulator); |
+ VisitForAccumulatorValue(function); |
__ mov(ContextOperand(esi, slot->index()), result_register()); |
int offset = Context::SlotOffset(slot->index()); |
__ mov(ebx, esi); |
@@ -605,7 +544,7 @@ |
if (mode == Variable::CONST) { |
__ push(Immediate(Factory::the_hole_value())); |
} else if (function != NULL) { |
- VisitForValue(function, kStack); |
+ VisitForStackValue(function); |
} else { |
__ push(Immediate(Smi::FromInt(0))); // No initial value! |
} |
@@ -618,13 +557,13 @@ |
if (function != NULL || mode == Variable::CONST) { |
// We are declaring a function or constant that rewrites to a |
// property. Use (keyed) IC to set the initial value. |
- VisitForValue(prop->obj(), kStack); |
+ VisitForStackValue(prop->obj()); |
if (function != NULL) { |
- VisitForValue(prop->key(), kStack); |
- VisitForValue(function, kAccumulator); |
+ VisitForStackValue(prop->key()); |
+ VisitForAccumulatorValue(function); |
__ pop(ecx); |
} else { |
- VisitForValue(prop->key(), kAccumulator); |
+ VisitForAccumulatorValue(prop->key()); |
__ mov(ecx, result_register()); |
__ mov(result_register(), Factory::the_hole_value()); |
} |
@@ -660,7 +599,7 @@ |
Breakable nested_statement(this, stmt); |
SetStatementPosition(stmt); |
// Keep the switch value on the stack until a case matches. |
- VisitForValue(stmt->tag(), kStack); |
+ VisitForStackValue(stmt->tag()); |
ZoneList<CaseClause*>* clauses = stmt->cases(); |
CaseClause* default_clause = NULL; // Can occur anywhere in the list. |
@@ -680,7 +619,7 @@ |
next_test.Unuse(); |
// Compile the label expression. |
- VisitForValue(clause->label(), kAccumulator); |
+ VisitForAccumulatorValue(clause->label()); |
// Perform the comparison as if via '==='. |
__ mov(edx, Operand(esp, 0)); // Switch value. |
@@ -738,7 +677,7 @@ |
// Get the object to enumerate over. Both SpiderMonkey and JSC |
// ignore null and undefined in contrast to the specification; see |
// ECMA-262 section 12.6.4. |
- VisitForValue(stmt->enumerable(), kAccumulator); |
+ VisitForAccumulatorValue(stmt->enumerable()); |
__ cmp(eax, Factory::undefined_value()); |
__ j(equal, &exit); |
__ cmp(eax, Factory::null_value()); |
@@ -918,13 +857,13 @@ |
__ push(Immediate(info)); |
__ CallRuntime(Runtime::kNewClosure, 2); |
} |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
Comment cmnt(masm_, "[ VariableProxy"); |
- EmitVariableLoad(expr->var(), context_); |
+ EmitVariableLoad(expr->var()); |
} |
@@ -1073,8 +1012,7 @@ |
} |
-void FullCodeGenerator::EmitVariableLoad(Variable* var, |
- Expression::Context context) { |
+void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
// Four cases: non-this global variables, lookup slots, all other |
// types of slots, and parameters that rewrite to explicit property |
// accesses on the arguments object. |
@@ -1094,7 +1032,7 @@ |
// Remember that the assembler may choose to do peephole optimization |
// (eg, push/pop elimination). |
__ nop(); |
- Apply(context, eax); |
+ context()->Plug(eax); |
} else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
Label done, slow; |
@@ -1110,7 +1048,7 @@ |
__ CallRuntime(Runtime::kLoadContextSlot, 2); |
__ bind(&done); |
- Apply(context, eax); |
+ context()->Plug(eax); |
} else if (slot != NULL) { |
Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) |
@@ -1126,9 +1064,9 @@ |
__ j(not_equal, &done); |
__ mov(eax, Factory::undefined_value()); |
__ bind(&done); |
- Apply(context, eax); |
+ context()->Plug(eax); |
} else { |
- Apply(context, slot); |
+ context()->Plug(slot); |
} |
} else { |
@@ -1161,7 +1099,7 @@ |
// call. It is treated specially by the LoadIC code. |
__ nop(); |
// Drop key and object left on the stack by IC. |
- Apply(context, eax); |
+ context()->Plug(eax); |
} |
} |
@@ -1216,7 +1154,7 @@ |
__ mov(edx, FieldOperand(ebx, size - kPointerSize)); |
__ mov(FieldOperand(eax, size - kPointerSize), edx); |
} |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -1253,7 +1191,7 @@ |
// Fall through. |
case ObjectLiteral::Property::COMPUTED: |
if (key->handle()->IsSymbol()) { |
- VisitForValue(value, kAccumulator); |
+ VisitForAccumulatorValue(value); |
__ mov(ecx, Immediate(key->handle())); |
__ mov(edx, Operand(esp, 0)); |
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
@@ -1264,18 +1202,18 @@ |
// Fall through. |
case ObjectLiteral::Property::PROTOTYPE: |
__ push(Operand(esp, 0)); // Duplicate receiver. |
- VisitForValue(key, kStack); |
- VisitForValue(value, kStack); |
+ VisitForStackValue(key); |
+ VisitForStackValue(value); |
__ CallRuntime(Runtime::kSetProperty, 3); |
break; |
case ObjectLiteral::Property::SETTER: |
case ObjectLiteral::Property::GETTER: |
__ push(Operand(esp, 0)); // Duplicate receiver. |
- VisitForValue(key, kStack); |
+ VisitForStackValue(key); |
__ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? |
Smi::FromInt(1) : |
Smi::FromInt(0))); |
- VisitForValue(value, kStack); |
+ VisitForStackValue(value); |
__ CallRuntime(Runtime::kDefineAccessor, 4); |
break; |
default: UNREACHABLE(); |
@@ -1283,9 +1221,9 @@ |
} |
if (result_saved) { |
- ApplyTOS(context_); |
+ context()->PlugTOS(); |
} else { |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
} |
@@ -1332,7 +1270,7 @@ |
__ push(eax); |
result_saved = true; |
} |
- VisitForValue(subexpr, kAccumulator); |
+ VisitForAccumulatorValue(subexpr); |
// Store the subexpression value in the array's elements. |
__ mov(ebx, Operand(esp, 0)); // Copy of array literal. |
@@ -1345,9 +1283,9 @@ |
} |
if (result_saved) { |
- ApplyTOS(context_); |
+ context()->PlugTOS(); |
} else { |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
} |
@@ -1380,39 +1318,38 @@ |
case NAMED_PROPERTY: |
if (expr->is_compound()) { |
// We need the receiver both on the stack and in the accumulator. |
- VisitForValue(property->obj(), kAccumulator); |
+ VisitForAccumulatorValue(property->obj()); |
__ push(result_register()); |
} else { |
- VisitForValue(property->obj(), kStack); |
+ VisitForStackValue(property->obj()); |
} |
break; |
case KEYED_PROPERTY: |
if (expr->is_compound()) { |
- VisitForValue(property->obj(), kStack); |
- VisitForValue(property->key(), kAccumulator); |
+ VisitForStackValue(property->obj()); |
+ VisitForAccumulatorValue(property->key()); |
__ mov(edx, Operand(esp, 0)); |
__ push(eax); |
} else { |
- VisitForValue(property->obj(), kStack); |
- VisitForValue(property->key(), kStack); |
+ VisitForStackValue(property->obj()); |
+ VisitForStackValue(property->key()); |
} |
break; |
} |
if (expr->is_compound()) { |
- Location saved_location = location_; |
- location_ = kAccumulator; |
- switch (assign_type) { |
- case VARIABLE: |
- EmitVariableLoad(expr->target()->AsVariableProxy()->var(), |
- Expression::kValue); |
- break; |
- case NAMED_PROPERTY: |
- EmitNamedPropertyLoad(property); |
- break; |
- case KEYED_PROPERTY: |
- EmitKeyedPropertyLoad(property); |
- break; |
+ { AccumulatorValueContext context(this); |
+ switch (assign_type) { |
+ case VARIABLE: |
+ EmitVariableLoad(expr->target()->AsVariableProxy()->var()); |
+ break; |
+ case NAMED_PROPERTY: |
+ EmitNamedPropertyLoad(property); |
+ break; |
+ case KEYED_PROPERTY: |
+ EmitKeyedPropertyLoad(property); |
+ break; |
+ } |
} |
Token::Value op = expr->binary_op(); |
@@ -1422,28 +1359,26 @@ |
ASSERT(constant == kRightConstant || constant == kNoConstants); |
if (constant == kNoConstants) { |
__ push(eax); // Left operand goes on the stack. |
- VisitForValue(expr->value(), kAccumulator); |
+ VisitForAccumulatorValue(expr->value()); |
} |
OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
? OVERWRITE_RIGHT |
: NO_OVERWRITE; |
SetSourcePosition(expr->position() + 1); |
+ AccumulatorValueContext context(this); |
if (ShouldInlineSmiCase(op)) { |
EmitInlineSmiBinaryOp(expr, |
op, |
- Expression::kValue, |
mode, |
expr->target(), |
expr->value(), |
constant); |
} else { |
- EmitBinaryOp(op, Expression::kValue, mode); |
+ EmitBinaryOp(op, mode); |
} |
- location_ = saved_location; |
- |
} else { |
- VisitForValue(expr->value(), kAccumulator); |
+ VisitForAccumulatorValue(expr->value()); |
} |
// Record source position before possible IC call. |
@@ -1453,8 +1388,7 @@ |
switch (assign_type) { |
case VARIABLE: |
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
- expr->op(), |
- context_); |
+ expr->op()); |
break; |
case NAMED_PROPERTY: |
EmitNamedPropertyAssignment(expr); |
@@ -1485,7 +1419,6 @@ |
void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, |
- Expression::Context context, |
OverwriteMode mode, |
bool left_is_constant_smi, |
Smi* value) { |
@@ -1509,12 +1442,11 @@ |
} |
__ CallStub(&stub); |
__ bind(&done); |
- Apply(context, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitConstantSmiSub(Expression* expr, |
- Expression::Context context, |
OverwriteMode mode, |
bool left_is_constant_smi, |
Smi* value) { |
@@ -1546,13 +1478,12 @@ |
GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); |
__ CallStub(&stub); |
__ bind(&done); |
- Apply(context, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr, |
Token::Value op, |
- Expression::Context context, |
OverwriteMode mode, |
Smi* value) { |
Label call_stub, smi_case, done; |
@@ -1609,13 +1540,12 @@ |
} |
__ bind(&done); |
- Apply(context, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr, |
Token::Value op, |
- Expression::Context context, |
OverwriteMode mode, |
Smi* value) { |
Label smi_case, done; |
@@ -1646,13 +1576,12 @@ |
} |
__ bind(&done); |
- Apply(context, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr, |
Token::Value op, |
- Expression::Context context, |
OverwriteMode mode, |
bool left_is_constant_smi, |
Smi* value) { |
@@ -1660,19 +1589,19 @@ |
case Token::BIT_OR: |
case Token::BIT_XOR: |
case Token::BIT_AND: |
- EmitConstantSmiBitOp(expr, op, context, mode, value); |
+ EmitConstantSmiBitOp(expr, op, mode, value); |
break; |
case Token::SHL: |
case Token::SAR: |
case Token::SHR: |
ASSERT(!left_is_constant_smi); |
- EmitConstantSmiShiftOp(expr, op, context, mode, value); |
+ EmitConstantSmiShiftOp(expr, op, mode, value); |
break; |
case Token::ADD: |
- EmitConstantSmiAdd(expr, context, mode, left_is_constant_smi, value); |
+ EmitConstantSmiAdd(expr, mode, left_is_constant_smi, value); |
break; |
case Token::SUB: |
- EmitConstantSmiSub(expr, context, mode, left_is_constant_smi, value); |
+ EmitConstantSmiSub(expr, mode, left_is_constant_smi, value); |
break; |
default: |
UNREACHABLE(); |
@@ -1682,18 +1611,17 @@ |
void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, |
Token::Value op, |
- Expression::Context context, |
OverwriteMode mode, |
Expression* left, |
Expression* right, |
ConstantOperand constant) { |
if (constant == kRightConstant) { |
Smi* value = Smi::cast(*right->AsLiteral()->handle()); |
- EmitConstantSmiBinaryOp(expr, op, context, mode, false, value); |
+ EmitConstantSmiBinaryOp(expr, op, mode, false, value); |
return; |
} else if (constant == kLeftConstant) { |
Smi* value = Smi::cast(*left->AsLiteral()->handle()); |
- EmitConstantSmiBinaryOp(expr, op, context, mode, true, value); |
+ EmitConstantSmiBinaryOp(expr, op, mode, true, value); |
return; |
} |
@@ -1787,12 +1715,11 @@ |
} |
__ bind(&done); |
- Apply(context, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
- Expression::Context context, |
OverwriteMode mode) { |
TypeInfo type = TypeInfo::Unknown(); |
GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS, type); |
@@ -1803,7 +1730,7 @@ |
__ push(result_register()); |
__ CallStub(&stub); |
} |
- Apply(context, eax); |
+ context()->Plug(eax); |
} |
@@ -1829,12 +1756,13 @@ |
switch (assign_type) { |
case VARIABLE: { |
Variable* var = expr->AsVariableProxy()->var(); |
- EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); |
+ EffectContext context(this); |
+ EmitVariableAssignment(var, Token::ASSIGN); |
break; |
} |
case NAMED_PROPERTY: { |
__ push(eax); // Preserve value. |
- VisitForValue(prop->obj(), kAccumulator); |
+ VisitForAccumulatorValue(prop->obj()); |
__ mov(edx, eax); |
__ pop(eax); // Restore value. |
__ mov(ecx, prop->key()->AsLiteral()->handle()); |
@@ -1845,8 +1773,8 @@ |
} |
case KEYED_PROPERTY: { |
__ push(eax); // Preserve value. |
- VisitForValue(prop->obj(), kStack); |
- VisitForValue(prop->key(), kAccumulator); |
+ VisitForStackValue(prop->obj()); |
+ VisitForAccumulatorValue(prop->key()); |
__ mov(ecx, eax); |
__ pop(edx); |
__ pop(eax); // Restore value. |
@@ -1860,8 +1788,7 @@ |
void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
- Token::Value op, |
- Expression::Context context) { |
+ Token::Value op) { |
// Left-hand sides that rewrite to explicit property accesses do not reach |
// here. |
ASSERT(var != NULL); |
@@ -1931,7 +1858,7 @@ |
__ bind(&done); |
} |
- Apply(context, eax); |
+ context()->Plug(eax); |
} |
@@ -1969,9 +1896,9 @@ |
__ push(Operand(esp, kPointerSize)); // Receiver is under value. |
__ CallRuntime(Runtime::kToFastProperties, 1); |
__ pop(eax); |
- DropAndApply(1, context_, eax); |
+ context()->DropAndPlug(1, eax); |
} else { |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
} |
@@ -2013,7 +1940,7 @@ |
__ pop(eax); |
} |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2022,15 +1949,15 @@ |
Expression* key = expr->key(); |
if (key->IsPropertyName()) { |
- VisitForValue(expr->obj(), kAccumulator); |
+ VisitForAccumulatorValue(expr->obj()); |
EmitNamedPropertyLoad(expr); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} else { |
- VisitForValue(expr->obj(), kStack); |
- VisitForValue(expr->key(), kAccumulator); |
+ VisitForStackValue(expr->obj()); |
+ VisitForAccumulatorValue(expr->key()); |
__ pop(edx); |
EmitKeyedPropertyLoad(expr); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
} |
@@ -2042,7 +1969,7 @@ |
ZoneList<Expression*>* args = expr->arguments(); |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
- VisitForValue(args->at(i), kStack); |
+ VisitForStackValue(args->at(i)); |
} |
__ Set(ecx, Immediate(name)); |
// Record source position of the IC call. |
@@ -2052,7 +1979,7 @@ |
__ call(ic, mode); |
// Restore context register. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2063,9 +1990,9 @@ |
ZoneList<Expression*>* args = expr->arguments(); |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
- VisitForValue(args->at(i), kStack); |
+ VisitForStackValue(args->at(i)); |
} |
- VisitForValue(key, kAccumulator); |
+ VisitForAccumulatorValue(key); |
__ mov(ecx, eax); |
// Record source position of the IC call. |
SetSourcePosition(expr->position()); |
@@ -2075,7 +2002,7 @@ |
__ call(ic, mode); |
// Restore context register. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2084,7 +2011,7 @@ |
ZoneList<Expression*>* args = expr->arguments(); |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
- VisitForValue(args->at(i), kStack); |
+ VisitForStackValue(args->at(i)); |
} |
// Record source position for debugger. |
SetSourcePosition(expr->position()); |
@@ -2093,7 +2020,7 @@ |
__ CallStub(&stub); |
// Restore context register. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
- DropAndApply(1, context_, eax); |
+ context()->DropAndPlug(1, eax); |
} |
@@ -2107,14 +2034,14 @@ |
// resolve the function we need to call and the receiver of the |
// call. Then we call the resolved function using the given |
// arguments. |
- VisitForValue(fun, kStack); |
+ VisitForStackValue(fun); |
__ push(Immediate(Factory::undefined_value())); // Reserved receiver slot. |
// Push the arguments. |
ZoneList<Expression*>* args = expr->arguments(); |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
- VisitForValue(args->at(i), kStack); |
+ VisitForStackValue(args->at(i)); |
} |
// Push copy of the function - found below the arguments. |
@@ -2143,7 +2070,7 @@ |
__ CallStub(&stub); |
// Restore context register. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
- DropAndApply(1, context_, eax); |
+ context()->DropAndPlug(1, eax); |
} else if (var != NULL && !var->is_this() && var->is_global()) { |
// Push global object as receiver for the call IC. |
__ push(CodeGenerator::GlobalObject()); |
@@ -2191,15 +2118,15 @@ |
Literal* key = prop->key()->AsLiteral(); |
if (key != NULL && key->handle()->IsSymbol()) { |
// Call to a named property, use call IC. |
- VisitForValue(prop->obj(), kStack); |
+ VisitForStackValue(prop->obj()); |
EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
} else { |
// Call to a keyed property. |
// For a synthetic property use keyed load IC followed by function call, |
// for a regular property use keyed CallIC. |
- VisitForValue(prop->obj(), kStack); |
+ VisitForStackValue(prop->obj()); |
if (prop->is_synthetic()) { |
- VisitForValue(prop->key(), kAccumulator); |
+ VisitForAccumulatorValue(prop->key()); |
// Record source code position for IC call. |
SetSourcePosition(prop->position()); |
__ pop(edx); // We do not need to keep the receiver. |
@@ -2230,7 +2157,7 @@ |
loop_depth() == 0) { |
lit->set_try_full_codegen(true); |
} |
- VisitForValue(fun, kStack); |
+ VisitForStackValue(fun); |
// Load global receiver object. |
__ mov(ebx, CodeGenerator::GlobalObject()); |
__ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
@@ -2249,13 +2176,13 @@ |
// Push constructor on the stack. If it's not a function it's used as |
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is |
// ignored. |
- VisitForValue(expr->expression(), kStack); |
+ VisitForStackValue(expr->expression()); |
// Push the arguments ("left-to-right") on the stack. |
ZoneList<Expression*>* args = expr->arguments(); |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
- VisitForValue(args->at(i), kStack); |
+ VisitForStackValue(args->at(i)); |
} |
// Call the construct call builtin that handles allocation and |
@@ -2268,59 +2195,59 @@ |
Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
__ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ test(eax, Immediate(kSmiTagMask)); |
Split(zero, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ test(eax, Immediate(kSmiTagMask | 0x80000000)); |
Split(zero, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(zero, if_false); |
@@ -2337,42 +2264,42 @@ |
__ cmp(ecx, LAST_JS_OBJECT_TYPE); |
Split(below_equal, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(equal, if_false); |
__ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx); |
Split(above_equal, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(zero, if_false); |
@@ -2381,7 +2308,7 @@ |
__ test(ebx, Immediate(1 << Map::kIsUndetectable)); |
Split(not_zero, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
@@ -2389,83 +2316,83 @@ |
ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
// Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only |
// used in a few functions in runtime.js which should not normally be hit by |
// this compiler. |
__ jmp(if_false); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(zero, if_false); |
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
Split(equal, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(equal, if_false); |
__ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); |
Split(equal, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(equal, if_false); |
__ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); |
Split(equal, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
@@ -2477,8 +2404,8 @@ |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
// Get the frame pointer for the calling frame. |
__ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
@@ -2496,7 +2423,7 @@ |
Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); |
Split(equal, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
@@ -2504,21 +2431,21 @@ |
ASSERT(args->length() == 2); |
// Load the two objects into registers and perform the comparison. |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kAccumulator); |
+ VisitForStackValue(args->at(0)); |
+ VisitForAccumulatorValue(args->at(1)); |
Label materialize_true, materialize_false; |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ pop(ebx); |
__ cmp(eax, Operand(ebx)); |
Split(equal, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
@@ -2527,12 +2454,12 @@ |
// ArgumentsAccessStub expects the key in edx and the formal |
// parameter count in eax. |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
__ mov(edx, eax); |
__ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); |
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
__ CallStub(&stub); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2555,7 +2482,7 @@ |
__ bind(&exit); |
if (FLAG_debug_code) __ AbortIfNotSmi(eax); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2563,7 +2490,7 @@ |
ASSERT(args->length() == 1); |
Label done, null, function, non_function_constructor; |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
// If the object is a smi, we return null. |
__ test(eax, Immediate(kSmiTagMask)); |
@@ -2610,7 +2537,7 @@ |
// All done. |
__ bind(&done); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2625,14 +2552,14 @@ |
ASSERT_EQ(args->length(), 3); |
#ifdef ENABLE_LOGGING_AND_PROFILING |
if (CodeGenerator::ShouldGenerateLog(args->at(0))) { |
- VisitForValue(args->at(1), kStack); |
- VisitForValue(args->at(2), kStack); |
+ VisitForStackValue(args->at(1)); |
+ VisitForStackValue(args->at(2)); |
__ CallRuntime(Runtime::kLog, 2); |
} |
#endif |
// Finally, we're expected to leave a value on the top of the stack. |
__ mov(eax, Factory::undefined_value()); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2680,7 +2607,7 @@ |
__ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset)); |
} |
__ mov(eax, edi); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2688,11 +2615,11 @@ |
// Load the arguments on the stack and call the stub. |
SubStringStub stub; |
ASSERT(args->length() == 3); |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kStack); |
- VisitForValue(args->at(2), kStack); |
+ VisitForStackValue(args->at(0)); |
+ VisitForStackValue(args->at(1)); |
+ VisitForStackValue(args->at(2)); |
__ CallStub(&stub); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2700,19 +2627,19 @@ |
// Load the arguments on the stack and call the stub. |
RegExpExecStub stub; |
ASSERT(args->length() == 4); |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kStack); |
- VisitForValue(args->at(2), kStack); |
- VisitForValue(args->at(3), kStack); |
+ VisitForStackValue(args->at(0)); |
+ VisitForStackValue(args->at(1)); |
+ VisitForStackValue(args->at(2)); |
+ VisitForStackValue(args->at(3)); |
__ CallStub(&stub); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); // Load the object. |
+ VisitForAccumulatorValue(args->at(0)); // Load the object. |
Label done; |
// If the object is a smi return the object. |
@@ -2724,25 +2651,25 @@ |
__ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); |
__ bind(&done); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { |
// Load the arguments on the stack and call the runtime function. |
ASSERT(args->length() == 2); |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kStack); |
+ VisitForStackValue(args->at(0)); |
+ VisitForStackValue(args->at(1)); |
__ CallRuntime(Runtime::kMath_pow, 2); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 2); |
- VisitForValue(args->at(0), kStack); // Load the object. |
- VisitForValue(args->at(1), kAccumulator); // Load the value. |
+ VisitForStackValue(args->at(0)); // Load the object. |
+ VisitForAccumulatorValue(args->at(1)); // Load the value. |
__ pop(ebx); // eax = value. ebx = object. |
Label done; |
@@ -2762,7 +2689,7 @@ |
__ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx); |
__ bind(&done); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2770,18 +2697,18 @@ |
ASSERT_EQ(args->length(), 1); |
// Load the argument on the stack and call the stub. |
- VisitForValue(args->at(0), kStack); |
+ VisitForStackValue(args->at(0)); |
NumberToStringStub stub; |
__ CallStub(&stub); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
Label done; |
StringCharFromCodeGenerator generator(eax, ebx); |
@@ -2792,15 +2719,15 @@ |
generator.GenerateSlow(masm_, call_helper); |
__ bind(&done); |
- Apply(context_, ebx); |
+ context()->Plug(ebx); |
} |
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 2); |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kAccumulator); |
+ VisitForStackValue(args->at(0)); |
+ VisitForAccumulatorValue(args->at(1)); |
Register object = ebx; |
Register index = eax; |
@@ -2839,15 +2766,15 @@ |
generator.GenerateSlow(masm_, call_helper); |
__ bind(&done); |
- Apply(context_, result); |
+ context()->Plug(result); |
} |
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 2); |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kAccumulator); |
+ VisitForStackValue(args->at(0)); |
+ VisitForAccumulatorValue(args->at(1)); |
Register object = ebx; |
Register index = eax; |
@@ -2888,31 +2815,31 @@ |
generator.GenerateSlow(masm_, call_helper); |
__ bind(&done); |
- Apply(context_, result); |
+ context()->Plug(result); |
} |
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { |
ASSERT_EQ(2, args->length()); |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kStack); |
+ VisitForStackValue(args->at(0)); |
+ VisitForStackValue(args->at(1)); |
StringAddStub stub(NO_STRING_ADD_FLAGS); |
__ CallStub(&stub); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { |
ASSERT_EQ(2, args->length()); |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kStack); |
+ VisitForStackValue(args->at(0)); |
+ VisitForStackValue(args->at(1)); |
StringCompareStub stub; |
__ CallStub(&stub); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2920,9 +2847,9 @@ |
// Load the argument on the stack and call the stub. |
TranscendentalCacheStub stub(TranscendentalCache::SIN); |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kStack); |
+ VisitForStackValue(args->at(0)); |
__ CallStub(&stub); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2930,18 +2857,18 @@ |
// Load the argument on the stack and call the stub. |
TranscendentalCacheStub stub(TranscendentalCache::COS); |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kStack); |
+ VisitForStackValue(args->at(0)); |
__ CallStub(&stub); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { |
// Load the argument on the stack and call the runtime function. |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kStack); |
+ VisitForStackValue(args->at(0)); |
__ CallRuntime(Runtime::kMath_sqrt, 1); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2949,38 +2876,38 @@ |
ASSERT(args->length() >= 2); |
int arg_count = args->length() - 2; // For receiver and function. |
- VisitForValue(args->at(0), kStack); // Receiver. |
+ VisitForStackValue(args->at(0)); // Receiver. |
for (int i = 0; i < arg_count; i++) { |
- VisitForValue(args->at(i + 1), kStack); |
+ VisitForStackValue(args->at(i + 1)); |
} |
- VisitForValue(args->at(arg_count + 1), kAccumulator); // Function. |
+ VisitForAccumulatorValue(args->at(arg_count + 1)); // Function. |
// InvokeFunction requires function in edi. Move it in there. |
if (!result_register().is(edi)) __ mov(edi, result_register()); |
ParameterCount count(arg_count); |
__ InvokeFunction(edi, count, CALL_FUNCTION); |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 3); |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kStack); |
- VisitForValue(args->at(2), kStack); |
+ VisitForStackValue(args->at(0)); |
+ VisitForStackValue(args->at(1)); |
+ VisitForStackValue(args->at(2)); |
__ CallRuntime(Runtime::kRegExpConstructResult, 3); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 3); |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kStack); |
- VisitForValue(args->at(2), kStack); |
+ VisitForStackValue(args->at(0)); |
+ VisitForStackValue(args->at(1)); |
+ VisitForStackValue(args->at(2)); |
__ CallRuntime(Runtime::kSwapElements, 3); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -2995,11 +2922,11 @@ |
if (jsfunction_result_caches->length() <= cache_id) { |
__ Abort("Attempt to use undefined cache."); |
__ mov(eax, Factory::undefined_value()); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
return; |
} |
- VisitForValue(args->at(1), kAccumulator); |
+ VisitForAccumulatorValue(args->at(1)); |
Register key = eax; |
Register cache = ebx; |
@@ -3028,7 +2955,7 @@ |
__ CallRuntime(Runtime::kGetFromCache, 2); |
__ bind(&done); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -3039,8 +2966,8 @@ |
Register left = ebx; |
Register tmp = ecx; |
- VisitForValue(args->at(0), kStack); |
- VisitForValue(args->at(1), kAccumulator); |
+ VisitForStackValue(args->at(0)); |
+ VisitForAccumulatorValue(args->at(1)); |
__ pop(left); |
Label done, fail, ok; |
@@ -3065,14 +2992,14 @@ |
__ mov(eax, Immediate(Factory::true_value())); |
__ bind(&done); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
if (FLAG_debug_code) { |
__ AbortIfNotString(eax); |
@@ -3082,21 +3009,21 @@ |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
__ test(FieldOperand(eax, String::kHashFieldOffset), |
Immediate(String::kContainsCachedArrayIndexMask)); |
Split(zero, if_true, if_false, fall_through); |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
- VisitForValue(args->at(0), kAccumulator); |
+ VisitForAccumulatorValue(args->at(0)); |
if (FLAG_debug_code) { |
__ AbortIfNotString(eax); |
@@ -3105,7 +3032,7 @@ |
__ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); |
__ IndexFromHash(eax, eax); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -3129,7 +3056,7 @@ |
// Push the arguments ("left-to-right"). |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
- VisitForValue(args->at(i), kStack); |
+ VisitForStackValue(args->at(i)); |
} |
if (expr->is_jsruntime()) { |
@@ -3144,7 +3071,7 @@ |
// Call the C runtime function. |
__ CallRuntime(expr->function(), arg_count); |
} |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
@@ -3158,20 +3085,20 @@ |
// Result of deleting non-property, non-variable reference is true. |
// The subexpression may have side effects. |
VisitForEffect(expr->expression()); |
- Apply(context_, true); |
+ context()->Plug(true); |
} else if (var != NULL && |
!var->is_global() && |
var->slot() != NULL && |
var->slot()->type() != Slot::LOOKUP) { |
// Result of deleting non-global, non-dynamic variables is false. |
// The subexpression does not have side effects. |
- Apply(context_, false); |
+ context()->Plug(false); |
} else { |
// Property or variable reference. Call the delete builtin with |
// object and property name as arguments. |
if (prop != NULL) { |
- VisitForValue(prop->obj(), kStack); |
- VisitForValue(prop->key(), kStack); |
+ VisitForStackValue(prop->obj()); |
+ VisitForStackValue(prop->key()); |
} else if (var->is_global()) { |
__ push(CodeGenerator::GlobalObject()); |
__ push(Immediate(var->name())); |
@@ -3185,7 +3112,7 @@ |
__ push(Immediate(var->name())); |
} |
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
break; |
} |
@@ -3193,26 +3120,7 @@ |
case Token::VOID: { |
Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
VisitForEffect(expr->expression()); |
- switch (context_) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- break; |
- case Expression::kEffect: |
- break; |
- case Expression::kValue: |
- switch (location_) { |
- case kAccumulator: |
- __ mov(result_register(), Factory::undefined_value()); |
- break; |
- case kStack: |
- __ push(Immediate(Factory::undefined_value())); |
- break; |
- } |
- break; |
- case Expression::kTest: |
- __ jmp(false_label_); |
- break; |
- } |
+ context()->Plug(Factory::undefined_value()); |
break; |
} |
@@ -3224,31 +3132,33 @@ |
Label* if_false = NULL; |
Label* fall_through = NULL; |
// Notice that the labels are swapped. |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_false, &if_true, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_false, &if_true, &fall_through); |
VisitForControl(expr->expression(), if_true, if_false, fall_through); |
- Apply(context_, if_false, if_true); // Labels swapped. |
+ context()->Plug(if_false, if_true); // Labels swapped. |
break; |
} |
case Token::TYPEOF: { |
Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); |
- VisitForTypeofValue(expr->expression(), kStack); |
+ { StackValueContext context(this); |
+ VisitForTypeofValue(expr->expression()); |
+ } |
__ CallRuntime(Runtime::kTypeof, 1); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
break; |
} |
case Token::ADD: { |
Comment cmt(masm_, "[ UnaryOperation (ADD)"); |
- VisitForValue(expr->expression(), kAccumulator); |
+ VisitForAccumulatorValue(expr->expression()); |
Label no_conversion; |
__ test(result_register(), Immediate(kSmiTagMask)); |
__ j(zero, &no_conversion); |
__ push(result_register()); |
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
__ bind(&no_conversion); |
- Apply(context_, result_register()); |
+ context()->Plug(result_register()); |
break; |
} |
@@ -3260,9 +3170,9 @@ |
GenericUnaryOpStub stub(Token::SUB, overwrite); |
// GenericUnaryOpStub expects the argument to be in the |
// accumulator register eax. |
- VisitForValue(expr->expression(), kAccumulator); |
+ VisitForAccumulatorValue(expr->expression()); |
__ CallStub(&stub); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
break; |
} |
@@ -3270,7 +3180,7 @@ |
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); |
// The generic unary operation stub expects the argument to be |
// in the accumulator register eax. |
- VisitForValue(expr->expression(), kAccumulator); |
+ VisitForAccumulatorValue(expr->expression()); |
Label done; |
if (ShouldInlineSmiCase(expr->op())) { |
Label call_stub; |
@@ -3287,7 +3197,7 @@ |
GenericUnaryOpStub stub(Token::BIT_NOT, mode); |
__ CallStub(&stub); |
__ bind(&done); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
break; |
} |
@@ -3323,24 +3233,21 @@ |
// Evaluate expression and get value. |
if (assign_type == VARIABLE) { |
ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
- Location saved_location = location_; |
- location_ = kAccumulator; |
- EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), |
- Expression::kValue); |
- location_ = saved_location; |
+ AccumulatorValueContext context(this); |
+ EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); |
} else { |
// Reserve space for result of postfix operation. |
- if (expr->is_postfix() && context_ != Expression::kEffect) { |
+ if (expr->is_postfix() && !context()->IsEffect()) { |
__ push(Immediate(Smi::FromInt(0))); |
} |
if (assign_type == NAMED_PROPERTY) { |
// Put the object both on the stack and in the accumulator. |
- VisitForValue(prop->obj(), kAccumulator); |
+ VisitForAccumulatorValue(prop->obj()); |
__ push(eax); |
EmitNamedPropertyLoad(prop); |
} else { |
- VisitForValue(prop->obj(), kStack); |
- VisitForValue(prop->key(), kAccumulator); |
+ VisitForStackValue(prop->obj()); |
+ VisitForAccumulatorValue(prop->key()); |
__ mov(edx, Operand(esp, 0)); |
__ push(eax); |
EmitKeyedPropertyLoad(prop); |
@@ -3359,29 +3266,21 @@ |
// Save result for postfix expressions. |
if (expr->is_postfix()) { |
- switch (context_) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- case Expression::kEffect: |
- // Do not save result. |
- break; |
- case Expression::kValue: |
- case Expression::kTest: |
- // Save the result on the stack. If we have a named or keyed property |
- // we store the result under the receiver that is currently on top |
- // of the stack. |
- switch (assign_type) { |
- case VARIABLE: |
- __ push(eax); |
- break; |
- case NAMED_PROPERTY: |
- __ mov(Operand(esp, kPointerSize), eax); |
- break; |
- case KEYED_PROPERTY: |
- __ mov(Operand(esp, 2 * kPointerSize), eax); |
- break; |
- } |
- break; |
+ if (!context()->IsEffect()) { |
+ // Save the result on the stack. If we have a named or keyed property |
+ // we store the result under the receiver that is currently on top |
+ // of the stack. |
+ switch (assign_type) { |
+ case VARIABLE: |
+ __ push(eax); |
+ break; |
+ case NAMED_PROPERTY: |
+ __ mov(Operand(esp, kPointerSize), eax); |
+ break; |
+ case KEYED_PROPERTY: |
+ __ mov(Operand(esp, 2 * kPointerSize), eax); |
+ break; |
+ } |
} |
} |
@@ -3419,19 +3318,20 @@ |
case VARIABLE: |
if (expr->is_postfix()) { |
// Perform the assignment as if via '='. |
- EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
- Token::ASSIGN, |
- Expression::kEffect); |
- // For all contexts except kEffect: We have the result on |
+ { |
+ EffectContext context(this); |
+ EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
+ Token::ASSIGN); |
+ } |
+ // For all contexts except EffectContext We have the result on |
// top of the stack. |
- if (context_ != Expression::kEffect) { |
- ApplyTOS(context_); |
+ if (!context()->IsEffect()) { |
+ context()->PlugTOS(); |
} |
} else { |
// Perform the assignment as if via '='. |
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
- Token::ASSIGN, |
- context_); |
+ Token::ASSIGN); |
} |
break; |
case NAMED_PROPERTY: { |
@@ -3443,11 +3343,11 @@ |
// site for it to patch. |
__ nop(); |
if (expr->is_postfix()) { |
- if (context_ != Expression::kEffect) { |
- ApplyTOS(context_); |
+ if (!context()->IsEffect()) { |
+ context()->PlugTOS(); |
} |
} else { |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
break; |
} |
@@ -3461,11 +3361,11 @@ |
__ nop(); |
if (expr->is_postfix()) { |
// Result is on the stack |
- if (context_ != Expression::kEffect) { |
- ApplyTOS(context_); |
+ if (!context()->IsEffect()) { |
+ context()->PlugTOS(); |
} |
} else { |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |
break; |
} |
@@ -3473,8 +3373,11 @@ |
} |
-void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { |
+void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
VariableProxy* proxy = expr->AsVariableProxy(); |
+ ASSERT(!context()->IsEffect()); |
+ ASSERT(!context()->IsTest()); |
+ |
if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
Comment cmnt(masm_, "Global variable"); |
__ mov(eax, CodeGenerator::GlobalObject()); |
@@ -3483,7 +3386,7 @@ |
// Use a regular load, not a contextual load, to avoid a reference |
// error. |
__ call(ic, RelocInfo::CODE_TARGET); |
- if (where == kStack) __ push(eax); |
+ context()->Plug(eax); |
} else if (proxy != NULL && |
proxy->var()->slot() != NULL && |
proxy->var()->slot()->type() == Slot::LOOKUP) { |
@@ -3500,10 +3403,10 @@ |
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
__ bind(&done); |
- if (where == kStack) __ push(eax); |
+ context()->Plug(eax); |
} else { |
// This expression cannot throw a reference error at the top level. |
- VisitForValue(expr, where); |
+ Visit(expr); |
} |
} |
@@ -3525,7 +3428,10 @@ |
if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; |
Handle<String> check = Handle<String>::cast(right_literal_value); |
- VisitForTypeofValue(left_unary->expression(), kAccumulator); |
+ { AccumulatorValueContext context(this); |
+ VisitForTypeofValue(left_unary->expression()); |
+ } |
+ |
if (check->Equals(Heap::number_symbol())) { |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(zero, if_true); |
@@ -3602,8 +3508,8 @@ |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
// First we try a fast inlined version of the compare when one of |
// the operands is a literal. |
@@ -3611,21 +3517,21 @@ |
Expression* left = expr->left(); |
Expression* right = expr->right(); |
if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
return; |
} |
- VisitForValue(expr->left(), kStack); |
+ VisitForStackValue(expr->left()); |
switch (expr->op()) { |
case Token::IN: |
- VisitForValue(expr->right(), kStack); |
+ VisitForStackValue(expr->right()); |
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
__ cmp(eax, Factory::true_value()); |
Split(equal, if_true, if_false, fall_through); |
break; |
case Token::INSTANCEOF: { |
- VisitForValue(expr->right(), kStack); |
+ VisitForStackValue(expr->right()); |
InstanceofStub stub; |
__ CallStub(&stub); |
__ test(eax, Operand(eax)); |
@@ -3635,7 +3541,7 @@ |
} |
default: { |
- VisitForValue(expr->right(), kAccumulator); |
+ VisitForAccumulatorValue(expr->right()); |
Condition cc = no_condition; |
bool strict = false; |
switch (op) { |
@@ -3692,7 +3598,7 @@ |
// Convert the result of the comparison into one expected for this |
// expression's context. |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
@@ -3701,10 +3607,10 @@ |
Label* if_true = NULL; |
Label* if_false = NULL; |
Label* fall_through = NULL; |
- PrepareTest(&materialize_true, &materialize_false, |
- &if_true, &if_false, &fall_through); |
+ context()->PrepareTest(&materialize_true, &materialize_false, |
+ &if_true, &if_false, &fall_through); |
- VisitForValue(expr->expression(), kAccumulator); |
+ VisitForAccumulatorValue(expr->expression()); |
__ cmp(eax, Factory::null_value()); |
if (expr->is_strict()) { |
Split(equal, if_true, if_false, fall_through); |
@@ -3720,13 +3626,13 @@ |
__ test(edx, Immediate(1 << Map::kIsUndetectable)); |
Split(not_zero, if_true, if_false, fall_through); |
} |
- Apply(context_, if_true, if_false); |
+ context()->Plug(if_true, if_false); |
} |
void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
__ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
- Apply(context_, eax); |
+ context()->Plug(eax); |
} |