| 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); | 
| } | 
|  | 
|  | 
|  |