Index: src/ia32/fast-codegen-ia32.cc |
=================================================================== |
--- src/ia32/fast-codegen-ia32.cc (revision 3576) |
+++ src/ia32/fast-codegen-ia32.cc (working copy) |
@@ -194,56 +194,106 @@ |
} |
-void FastCodeGenerator::Move(Expression::Context context, Register source) { |
+void FastCodeGenerator::Apply(Expression::Context context, |
+ Slot* slot, |
+ Register scratch) { |
Lasse Reichstein
2010/01/12 08:30:05
This function looks generic enough that it could b
|
switch (context) { |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
break; |
+ case Expression::kValue: { |
+ MemOperand location = EmitSlotSearch(slot, scratch); |
+ __ push(location); |
+ break; |
+ } |
+ case Expression::kTest: |
+ case Expression::kValueTest: |
+ case Expression::kTestValue: |
+ Move(scratch, slot); |
+ Apply(context, scratch); |
+ break; |
+ } |
+} |
+ |
+ |
+void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
Lasse Reichstein
2010/01/12 08:30:05
If we had MacroAssembler::Push(Handle<Object> sour
|
+ switch (context) { |
+ case Expression::kUninitialized: |
+ UNREACHABLE(); |
+ case Expression::kEffect: |
+ break; |
case Expression::kValue: |
- __ push(source); |
+ __ push(Immediate(lit->handle())); |
break; |
case Expression::kTest: |
- TestAndBranch(source, true_label_, false_label_); |
+ case Expression::kValueTest: |
+ case Expression::kTestValue: |
+ __ mov(eax, lit->handle()); |
+ Apply(context, eax); |
break; |
+ } |
+} |
+ |
+ |
+void FastCodeGenerator::ApplyTOS(Expression::Context context) { |
+ switch (context) { |
+ case Expression::kUninitialized: |
+ UNREACHABLE(); |
+ case Expression::kEffect: |
+ __ Drop(1); |
+ break; |
+ case Expression::kValue: |
+ break; |
+ case Expression::kTest: |
+ __ pop(eax); |
+ TestAndBranch(eax, true_label_, false_label_); |
+ break; |
case Expression::kValueTest: { |
Label discard; |
- __ push(source); |
- TestAndBranch(source, true_label_, &discard); |
+ __ mov(eax, Operand(esp, 0)); |
Lasse Reichstein
2010/01/12 08:30:05
With a function like MacroAssembler::MoveToStack(i
|
+ TestAndBranch(eax, true_label_, &discard); |
__ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(false_label_); |
break; |
} |
case Expression::kTestValue: { |
Label discard; |
- __ push(source); |
- TestAndBranch(source, &discard, false_label_); |
+ __ mov(eax, Operand(esp, 0)); |
+ TestAndBranch(eax, &discard, false_label_); |
__ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(true_label_); |
} |
} |
} |
-void FastCodeGenerator::MoveTOS(Expression::Context context) { |
+void FastCodeGenerator::DropAndApply(int count, |
+ Expression::Context context, |
+ Register reg) { |
Lasse Reichstein
2010/01/12 08:30:05
And this one too!
(A good abstraction of the stack
|
+ ASSERT(count > 0); |
+ ASSERT(!reg.is(esp)); |
switch (context) { |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
- __ Drop(1); |
+ __ Drop(count); |
break; |
case Expression::kValue: |
+ if (count > 1) __ Drop(count - 1); |
+ __ mov(Operand(esp, 0), reg); |
break; |
case Expression::kTest: |
- __ pop(eax); |
- TestAndBranch(eax, true_label_, false_label_); |
+ __ Drop(count); |
+ TestAndBranch(reg, true_label_, false_label_); |
break; |
case Expression::kValueTest: { |
Label discard; |
- __ mov(eax, Operand(esp, 0)); |
- TestAndBranch(eax, true_label_, &discard); |
+ if (count > 1) __ Drop(count - 1); |
+ __ mov(Operand(esp, 0), reg); |
+ TestAndBranch(reg, true_label_, &discard); |
__ bind(&discard); |
__ Drop(1); |
__ jmp(false_label_); |
@@ -251,11 +301,13 @@ |
} |
case Expression::kTestValue: { |
Label discard; |
- __ mov(eax, Operand(esp, 0)); |
- TestAndBranch(eax, &discard, false_label_); |
+ if (count > 1) __ Drop(count - 1); |
+ __ mov(Operand(esp, 0), reg); |
+ TestAndBranch(reg, &discard, false_label_); |
__ bind(&discard); |
__ Drop(1); |
__ jmp(true_label_); |
+ break; |
} |
} |
} |
@@ -286,48 +338,6 @@ |
} |
-void FastCodeGenerator::Move(Expression::Context context, |
- Slot* source, |
- Register scratch) { |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- case Expression::kEffect: |
- break; |
- case Expression::kValue: { |
- MemOperand location = EmitSlotSearch(source, scratch); |
- __ push(location); |
- break; |
- } |
- case Expression::kTest: |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
- Move(scratch, source); |
- Move(context, scratch); |
- break; |
- } |
-} |
- |
- |
-void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- case Expression::kEffect: |
- break; |
- case Expression::kValue: |
- __ push(Immediate(expr->handle())); |
- break; |
- case Expression::kTest: |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
- __ mov(eax, expr->handle()); |
- Move(context, eax); |
- break; |
- } |
-} |
- |
- |
void FastCodeGenerator::Move(Slot* dst, |
Register src, |
Register scratch1, |
@@ -344,55 +354,6 @@ |
} |
-void FastCodeGenerator::DropAndMove(Expression::Context context, |
- Register source, |
- int count) { |
- ASSERT(count > 0); |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- case Expression::kEffect: |
- __ add(Operand(esp), Immediate(count * kPointerSize)); |
- break; |
- case Expression::kValue: |
- if (count > 1) { |
- __ add(Operand(esp), Immediate((count - 1) * kPointerSize)); |
- } |
- __ mov(Operand(esp, 0), source); |
- break; |
- case Expression::kTest: |
- ASSERT(!source.is(esp)); |
- __ add(Operand(esp), Immediate(count * kPointerSize)); |
- TestAndBranch(source, true_label_, false_label_); |
- break; |
- case Expression::kValueTest: { |
- Label discard; |
- if (count > 1) { |
- __ add(Operand(esp), Immediate((count - 1) * kPointerSize)); |
- } |
- __ mov(Operand(esp, 0), source); |
- TestAndBranch(source, true_label_, &discard); |
- __ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
- __ jmp(false_label_); |
- break; |
- } |
- case Expression::kTestValue: { |
- Label discard; |
- if (count > 1) { |
- __ add(Operand(esp), Immediate((count - 1) * kPointerSize)); |
- } |
- __ mov(Operand(esp, 0), source); |
- TestAndBranch(source, &discard, false_label_); |
- __ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
- __ jmp(true_label_); |
- break; |
- } |
- } |
-} |
- |
- |
void FastCodeGenerator::TestAndBranch(Register source, |
Label* true_label, |
Label* false_label) { |
@@ -518,7 +479,7 @@ |
// Value in eax is ignored (declarations are statements). Receiver |
// and key on stack are discarded. |
- __ add(Operand(esp), Immediate(2 * kPointerSize)); |
+ __ Drop(2); |
} |
} |
} |
@@ -548,7 +509,7 @@ |
__ push(esi); |
__ push(Immediate(boilerplate)); |
__ CallRuntime(Runtime::kNewClosure, 2); |
- Move(expr->context(), eax); |
+ Apply(expr->context(), eax); |
} |
@@ -575,7 +536,7 @@ |
// Remember that the assembler may choose to do peephole optimization |
// (eg, push/pop elimination). |
__ nop(); |
- DropAndMove(context, eax); |
+ DropAndApply(1, context, eax); |
} else if (rewrite->AsSlot() != NULL) { |
Slot* slot = rewrite->AsSlot(); |
if (FLAG_debug_code) { |
@@ -594,42 +555,43 @@ |
break; |
} |
} |
- Move(context, slot, eax); |
+ Apply(context, slot, eax); |
} else { |
- Comment cmnt(masm_, "Variable rewritten to Property"); |
- // A variable has been rewritten into an explicit access to |
- // an object property. |
+ Comment cmnt(masm_, "Variable rewritten to property"); |
+ // A variable has been rewritten into an explicit access to an object |
+ // property. |
Property* property = rewrite->AsProperty(); |
ASSERT_NOT_NULL(property); |
- // Currently the only parameter expressions that can occur are |
- // on the form "slot[literal]". |
+ // The only property expressions that can occur are of the form |
+ // "slot[literal]". |
- // Check that the object is in a slot. |
+ // Assert that the object is in a slot. |
Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); |
ASSERT_NOT_NULL(object_var); |
Slot* object_slot = object_var->slot(); |
ASSERT_NOT_NULL(object_slot); |
// Load the object. |
- Move(Expression::kValue, object_slot, eax); |
+ MemOperand object_loc = EmitSlotSearch(object_slot, eax); |
+ __ push(object_loc); |
- // Check that the key is a smi. |
+ // Assert that the key is a smi. |
Literal* key_literal = property->key()->AsLiteral(); |
ASSERT_NOT_NULL(key_literal); |
ASSERT(key_literal->handle()->IsSmi()); |
// Load the key. |
- Move(Expression::kValue, key_literal); |
+ __ push(Immediate(key_literal->handle())); |
- // Do a KEYED property load. |
+ // Do a keyed property load. |
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
__ call(ic, RelocInfo::CODE_TARGET); |
- // Notice: We must not have a "test eax, ..." instruction after |
- // the call. It is treated specially by the LoadIC code. |
+ // Notice: We must not have a "test eax, ..." instruction after the |
+ // call. It is treated specially by the LoadIC code. |
__ nop(); |
Lasse Reichstein
2010/01/12 08:30:05
Can we assume that DropAndMove does not start with
|
// Drop key and object left on the stack by IC. |
- DropAndMove(context, eax, 2); |
+ DropAndApply(2, context, eax); |
} |
} |
@@ -657,7 +619,7 @@ |
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
// Label done: |
__ bind(&done); |
- Move(expr->context(), eax); |
+ Apply(expr->context(), eax); |
} |
@@ -733,7 +695,7 @@ |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
- if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); |
+ if (result_saved) __ Drop(1); |
break; |
case Expression::kValue: |
if (!result_saved) __ push(eax); |
@@ -747,7 +709,7 @@ |
if (!result_saved) __ push(eax); |
TestAndBranch(eax, true_label_, &discard); |
__ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(false_label_); |
break; |
} |
@@ -756,7 +718,7 @@ |
if (!result_saved) __ push(eax); |
TestAndBranch(eax, &discard, false_label_); |
__ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ Drop (1); |
__ jmp(true_label_); |
break; |
} |
@@ -812,7 +774,7 @@ |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
- if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); |
+ if (result_saved) __ Drop(1); |
break; |
case Expression::kValue: |
if (!result_saved) __ push(eax); |
@@ -826,7 +788,7 @@ |
if (!result_saved) __ push(eax); |
TestAndBranch(eax, true_label_, &discard); |
__ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(false_label_); |
break; |
} |
@@ -835,7 +797,7 @@ |
if (!result_saved) __ push(eax); |
TestAndBranch(eax, &discard, false_label_); |
__ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(true_label_); |
break; |
} |
@@ -850,7 +812,7 @@ |
__ mov(ecx, Immediate(key->handle())); |
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
__ call(ic, RelocInfo::CODE_TARGET); |
- Move(context, eax); |
+ Apply(context, eax); |
} |
@@ -859,7 +821,7 @@ |
SetSourcePosition(prop->position()); |
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
__ call(ic, RelocInfo::CODE_TARGET); |
- Move(context, eax); |
+ Apply(context, eax); |
} |
@@ -869,7 +831,7 @@ |
NO_OVERWRITE, |
NO_GENERIC_BINARY_FLAGS); |
__ CallStub(&stub); |
- Move(context, eax); |
+ Apply(context, eax); |
} |
@@ -887,7 +849,7 @@ |
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
__ call(ic, RelocInfo::CODE_TARGET); |
// Overwrite the receiver on the stack with the result if needed. |
- DropAndMove(context, eax); |
+ DropAndApply(1, context, eax); |
} else if (var->slot() != NULL) { |
Slot* slot = var->slot(); |
@@ -919,7 +881,7 @@ |
__ mov(target, eax); |
TestAndBranch(eax, true_label_, &discard); |
__ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(false_label_); |
break; |
} |
@@ -929,7 +891,7 @@ |
__ mov(target, eax); |
TestAndBranch(eax, &discard, false_label_); |
__ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(true_label_); |
break; |
} |
@@ -950,9 +912,8 @@ |
} |
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
__ RecordWrite(ecx, offset, eax, ebx); |
- if (context != Expression::kEffect && |
- context != Expression::kValue) { |
- Move(context, edx); |
+ if (context != Expression::kEffect && context != Expression::kValue) { |
+ Apply(context, edx); |
} |
break; |
} |
@@ -996,7 +957,7 @@ |
__ pop(eax); |
} |
- DropAndMove(expr->context(), eax); |
+ DropAndApply(1, expr->context(), eax); |
} |
@@ -1029,34 +990,32 @@ |
} |
// Receiver and key are still on stack. |
- __ add(Operand(esp), Immediate(2 * kPointerSize)); |
- Move(expr->context(), eax); |
+ DropAndApply(2, expr->context(), eax); |
} |
void FastCodeGenerator::VisitProperty(Property* expr) { |
Comment cmnt(masm_, "[ Property"); |
Expression* key = expr->key(); |
- uint32_t dummy; |
// Record the source position for the property load. |
SetSourcePosition(expr->position()); |
- // Evaluate receiver. |
+ // Evaluate the receiver. |
Visit(expr->obj()); |
- if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && |
- !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { |
- // Do a NAMED property load. |
- // The IC expects the property name in ecx and the receiver on the stack. |
+ if (key->IsPropertyName()) { |
+ // Do a named property load. The IC expects the property name in ecx |
+ // and the receiver on the stack. |
__ mov(ecx, Immediate(key->AsLiteral()->handle())); |
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
__ call(ic, RelocInfo::CODE_TARGET); |
// By emitting a nop we make sure that we do not have a test eax |
// instruction after the call it is treated specially by the LoadIC code. |
__ nop(); |
+ DropAndApply(1, expr->context(), eax); |
} else { |
- // Do a KEYED property load. |
+ // Do a keyed property load. |
Visit(expr->key()); |
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
__ call(ic, RelocInfo::CODE_TARGET); |
@@ -1064,9 +1023,8 @@ |
// instruction after the call it is treated specially by the LoadIC code. |
__ nop(); |
// Drop key left on the stack by IC. |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ DropAndApply(2, expr->context(), eax); |
} |
- DropAndMove(expr->context(), eax); |
} |
@@ -1088,7 +1046,7 @@ |
__ call(ic, mode); |
// Restore context register. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
- Move(expr->context(), eax); |
+ Apply(expr->context(), eax); |
} |
@@ -1105,7 +1063,7 @@ |
__ CallStub(&stub); |
// Restore context register. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
- DropAndMove(expr->context(), eax); |
+ DropAndApply(1, expr->context(), eax); |
} |
@@ -1146,7 +1104,7 @@ |
// instruction after the call it is treated specially by the LoadIC code. |
__ nop(); |
// Drop key left on the stack by IC. |
- __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ Drop(1); |
// Pop receiver. |
__ pop(ebx); |
// Push result (function). |
@@ -1214,7 +1172,7 @@ |
__ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
// Replace function on TOS with result in eax, or pop it. |
- DropAndMove(expr->context(), eax); |
+ DropAndApply(1, expr->context(), eax); |
} |
@@ -1247,7 +1205,7 @@ |
// Call the C runtime function. |
__ CallRuntime(expr->function(), arg_count); |
} |
- Move(expr->context(), eax); |
+ Apply(expr->context(), eax); |
} |
@@ -1369,7 +1327,7 @@ |
} |
__ CallRuntime(Runtime::kTypeof, 1); |
- Move(expr->context(), eax); |
+ Apply(expr->context(), eax); |
break; |
} |
@@ -1469,7 +1427,7 @@ |
// For all contexts except kEffect: We have the result on |
// top of the stack. |
if (expr->context() != Expression::kEffect) { |
- MoveTOS(expr->context()); |
+ ApplyTOS(expr->context()); |
} |
} else { |
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
@@ -1486,10 +1444,10 @@ |
if (expr->is_postfix()) { |
__ Drop(1); // Result is on the stack under the receiver. |
if (expr->context() != Expression::kEffect) { |
- MoveTOS(expr->context()); |
+ ApplyTOS(expr->context()); |
} |
} else { |
- DropAndMove(expr->context(), eax); |
+ DropAndApply(1, expr->context(), eax); |
} |
break; |
} |
@@ -1502,10 +1460,10 @@ |
if (expr->is_postfix()) { |
__ Drop(2); // Result is on the stack under the key and the receiver. |
if (expr->context() != Expression::kEffect) { |
- MoveTOS(expr->context()); |
+ ApplyTOS(expr->context()); |
} |
} else { |
- DropAndMove(expr->context(), eax, 2); |
+ DropAndApply(2, expr->context(), eax); |
} |
break; |
} |
@@ -1548,7 +1506,7 @@ |
NO_OVERWRITE, |
NO_GENERIC_BINARY_FLAGS); |
__ CallStub(&stub); |
- Move(expr->context(), eax); |
+ Apply(expr->context(), eax); |
break; |
} |
@@ -1719,7 +1677,7 @@ |
void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
__ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
- Move(expr->context(), eax); |
+ Apply(expr->context(), eax); |
} |