Index: src/x64/fast-codegen-x64.cc |
=================================================================== |
--- src/x64/fast-codegen-x64.cc (revision 3576) |
+++ src/x64/fast-codegen-x64.cc (working copy) |
@@ -202,57 +202,106 @@ |
} |
-void FastCodeGenerator::Move(Expression::Context context, Register source) { |
+void FastCodeGenerator::Apply(Expression::Context context, |
+ Slot* slot, |
+ Register scratch) { |
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) { |
+ switch (context) { |
+ case Expression::kUninitialized: |
+ UNREACHABLE(); |
+ case Expression::kEffect: |
+ break; |
case Expression::kValue: |
- __ push(source); |
+ __ Push(lit->handle()); |
break; |
case Expression::kTest: |
- TestAndBranch(source, true_label_, false_label_); |
+ case Expression::kValueTest: |
+ case Expression::kTestValue: |
+ __ Move(rax, lit->handle()); |
+ Apply(context, rax); |
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(rax); |
+ TestAndBranch(rax, true_label_, false_label_); |
+ break; |
case Expression::kValueTest: { |
Label discard; |
- __ push(source); |
- TestAndBranch(source, true_label_, &discard); |
+ __ movq(rax, Operand(rsp, 0)); |
+ TestAndBranch(rax, true_label_, &discard); |
__ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(false_label_); |
break; |
} |
case Expression::kTestValue: { |
Label discard; |
- __ push(source); |
- TestAndBranch(source, &discard, false_label_); |
+ __ movq(rax, Operand(rsp, 0)); |
+ TestAndBranch(rax, &discard, false_label_); |
__ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(true_label_); |
- break; |
} |
} |
} |
-void FastCodeGenerator::MoveTOS(Expression::Context context) { |
+void FastCodeGenerator::DropAndApply(int count, |
+ Expression::Context context, |
+ Register reg) { |
+ ASSERT(count > 0); |
+ ASSERT(!reg.is(rsp)); |
switch (context) { |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
- __ Drop(1); |
+ __ Drop(count); |
break; |
case Expression::kValue: |
+ if (count > 1) __ Drop(count - 1); |
+ __ movq(Operand(rsp, 0), reg); |
break; |
case Expression::kTest: |
- __ pop(rax); |
- TestAndBranch(rax, true_label_, false_label_); |
+ __ Drop(count); |
+ TestAndBranch(reg, true_label_, false_label_); |
break; |
case Expression::kValueTest: { |
Label discard; |
- __ movq(rax, Operand(rsp, 0)); |
- TestAndBranch(rax, true_label_, &discard); |
+ if (count > 1) __ Drop(count - 1); |
+ __ movq(Operand(rsp, 0), reg); |
+ TestAndBranch(reg, true_label_, &discard); |
__ bind(&discard); |
__ Drop(1); |
__ jmp(false_label_); |
@@ -260,11 +309,13 @@ |
} |
case Expression::kTestValue: { |
Label discard; |
- __ movq(rax, Operand(rsp, 0)); |
- TestAndBranch(rax, &discard, false_label_); |
+ if (count > 1) __ Drop(count - 1); |
+ __ movq(Operand(rsp, 0), reg); |
+ TestAndBranch(reg, &discard, false_label_); |
__ bind(&discard); |
__ Drop(1); |
__ jmp(true_label_); |
+ break; |
} |
} |
} |
@@ -295,48 +346,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(expr->handle()); |
- break; |
- case Expression::kTest: |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
- __ Move(rax, expr->handle()); |
- Move(context, rax); |
- break; |
- } |
-} |
- |
- |
void FastCodeGenerator::Move(Slot* dst, |
Register src, |
Register scratch1, |
@@ -353,52 +362,6 @@ |
} |
-void FastCodeGenerator::DropAndMove(Expression::Context context, |
- Register source, |
- int drop_count) { |
- ASSERT(drop_count > 0); |
- switch (context) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- case Expression::kEffect: |
- __ addq(rsp, Immediate(drop_count * kPointerSize)); |
- break; |
- case Expression::kValue: |
- if (drop_count > 1) { |
- __ addq(rsp, Immediate((drop_count - 1) * kPointerSize)); |
- } |
- __ movq(Operand(rsp, 0), source); |
- break; |
- case Expression::kTest: |
- ASSERT(!source.is(rsp)); |
- __ addq(rsp, Immediate(drop_count * kPointerSize)); |
- TestAndBranch(source, true_label_, false_label_); |
- break; |
- case Expression::kValueTest: { |
- Label discard; |
- if (drop_count > 1) { |
- __ addq(rsp, Immediate((drop_count - 1) * kPointerSize)); |
- } |
- __ movq(Operand(rsp, 0), source); |
- TestAndBranch(source, true_label_, &discard); |
- __ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
- __ jmp(false_label_); |
- break; |
- } |
- case Expression::kTestValue: { |
- Label discard; |
- __ movq(Operand(rsp, 0), source); |
- TestAndBranch(source, &discard, false_label_); |
- __ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
- __ jmp(true_label_); |
- break; |
- } |
- } |
-} |
- |
- |
void FastCodeGenerator::TestAndBranch(Register source, |
Label* true_label, |
Label* false_label) { |
@@ -528,7 +491,7 @@ |
// Value in rax is ignored (declarations are statements). Receiver |
// and key on stack are discarded. |
- __ addq(rsp, Immediate(2 * kPointerSize)); |
+ __ Drop(2); |
} |
} |
} |
@@ -558,7 +521,7 @@ |
__ push(rsi); |
__ Push(boilerplate); |
__ CallRuntime(Runtime::kNewClosure, 2); |
- Move(expr->context(), rax); |
+ Apply(expr->context(), rax); |
} |
@@ -585,7 +548,7 @@ |
// is no test rax instruction here. |
__ nop(); |
- DropAndMove(context, rax); |
+ DropAndApply(1, context, rax); |
} else if (rewrite->AsSlot() != NULL) { |
Slot* slot = rewrite->AsSlot(); |
if (FLAG_debug_code) { |
@@ -604,41 +567,43 @@ |
break; |
} |
} |
- Move(context, slot, rax); |
+ Apply(context, slot, rax); |
} else { |
- // 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 = property->obj()->AsVariableProxy()->AsVariable(); |
ASSERT_NOT_NULL(object); |
Slot* object_slot = object->slot(); |
ASSERT_NOT_NULL(object_slot); |
// Load the object. |
- Move(Expression::kValue, object_slot, rax); |
+ MemOperand object_loc = EmitSlotSearch(object_slot, rax); |
+ __ 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(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 rax, ..." instruction after |
- // the call. It is treated specially by the LoadIC code. |
+ // Notice: We must not have a "test rax, ..." instruction after the |
+ // call. It is treated specially by the LoadIC code. |
// Drop key and object left on the stack by IC, and push the result. |
- DropAndMove(context, rax, 2); |
+ DropAndApply(2, context, rax); |
} |
} |
@@ -666,7 +631,7 @@ |
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
// Label done: |
__ bind(&done); |
- Move(expr->context(), rax); |
+ Apply(expr->context(), rax); |
} |
@@ -742,7 +707,7 @@ |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
- if (result_saved) __ addq(rsp, Immediate(kPointerSize)); |
+ if (result_saved) __ Drop(1); |
break; |
case Expression::kValue: |
if (!result_saved) __ push(rax); |
@@ -756,7 +721,7 @@ |
if (!result_saved) __ push(rax); |
TestAndBranch(rax, true_label_, &discard); |
__ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(false_label_); |
break; |
} |
@@ -765,7 +730,7 @@ |
if (!result_saved) __ push(rax); |
TestAndBranch(rax, &discard, false_label_); |
__ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(true_label_); |
break; |
} |
@@ -821,7 +786,7 @@ |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
- if (result_saved) __ addq(rsp, Immediate(kPointerSize)); |
+ if (result_saved) __ Drop(1); |
break; |
case Expression::kValue: |
if (!result_saved) __ push(rax); |
@@ -835,7 +800,7 @@ |
if (!result_saved) __ push(rax); |
TestAndBranch(rax, true_label_, &discard); |
__ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(false_label_); |
break; |
} |
@@ -844,7 +809,7 @@ |
if (!result_saved) __ push(rax); |
TestAndBranch(rax, &discard, false_label_); |
__ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(true_label_); |
break; |
} |
@@ -859,7 +824,7 @@ |
__ Move(rcx, key->handle()); |
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
__ Call(ic, RelocInfo::CODE_TARGET); |
- Move(context, rax); |
+ Apply(context, rax); |
} |
@@ -868,7 +833,7 @@ |
SetSourcePosition(prop->position()); |
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
__ Call(ic, RelocInfo::CODE_TARGET); |
- Move(context, rax); |
+ Apply(context, rax); |
} |
@@ -878,7 +843,7 @@ |
NO_OVERWRITE, |
NO_GENERIC_BINARY_FLAGS); |
__ CallStub(&stub); |
- Move(context, rax); |
+ Apply(context, rax); |
} |
@@ -896,7 +861,7 @@ |
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
__ Call(ic, RelocInfo::CODE_TARGET); |
// Overwrite the global object on the stack with the result if needed. |
- DropAndMove(context, rax); |
+ DropAndApply(1, context, rax); |
} else if (var->slot() != NULL) { |
Slot* slot = var->slot(); |
@@ -928,7 +893,7 @@ |
__ movq(target, rax); |
TestAndBranch(rax, true_label_, &discard); |
__ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(false_label_); |
break; |
} |
@@ -938,7 +903,7 @@ |
__ movq(target, rax); |
TestAndBranch(rax, &discard, false_label_); |
__ bind(&discard); |
- __ addq(rsp, Immediate(kPointerSize)); |
+ __ Drop(1); |
__ jmp(true_label_); |
break; |
} |
@@ -959,9 +924,8 @@ |
} |
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
__ RecordWrite(rcx, offset, rax, rbx); |
- if (context != Expression::kEffect && |
- context != Expression::kValue) { |
- Move(context, rdx); |
+ if (context != Expression::kEffect && context != Expression::kValue) { |
+ Apply(context, rdx); |
} |
break; |
} |
@@ -1005,7 +969,7 @@ |
__ pop(rax); |
} |
- DropAndMove(expr->context(), rax); |
+ DropAndApply(1, expr->context(), rax); |
} |
@@ -1038,15 +1002,13 @@ |
} |
// Receiver and key are still on stack. |
- __ addq(rsp, Immediate(2 * kPointerSize)); |
- Move(expr->context(), rax); |
+ DropAndApply(2, expr->context(), rax); |
} |
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()); |
@@ -1054,29 +1016,27 @@ |
// Evaluate 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 rcx and the receiver on the stack. |
+ if (key->IsPropertyName()) { |
+ // Do a named property load. The IC expects the property name in rcx |
+ // and the receiver on the stack. |
__ Move(rcx, 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 rax,..." |
// instruction after the call it is treated specially by the LoadIC code. |
__ nop(); |
+ DropAndApply(1, expr->context(), rax); |
} 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); |
- // Notice: We must not have a "test rax, ..." instruction after |
- // the call. It is treated specially by the LoadIC code. |
- |
- // Drop key left on the stack by IC. |
- __ addq(rsp, Immediate(kPointerSize)); |
+ // Notice: We must not have a "test rax, ..." instruction after the |
+ // call. It is treated specially by the LoadIC code. |
+ __ nop(); |
+ // Drop key and receiver left on the stack by IC. |
+ DropAndApply(2, expr->context(), rax); |
} |
- DropAndMove(expr->context(), rax); |
} |
@@ -1099,7 +1059,7 @@ |
// Restore context register. |
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
// Discard the function left on TOS. |
- DropAndMove(expr->context(), rax); |
+ DropAndApply(1, expr->context(), rax); |
} |
@@ -1117,7 +1077,7 @@ |
// Restore context register. |
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
// Discard the function left on TOS. |
- DropAndMove(expr->context(), rax); |
+ DropAndApply(1, expr->context(), rax); |
} |
@@ -1161,7 +1121,7 @@ |
// instruction after the call it is treated specially by the LoadIC code. |
__ nop(); |
// Drop key left on the stack by IC. |
- __ addq(rsp, Immediate(kPointerSize)); |
+ __ Drop(1); |
// Pop receiver. |
__ pop(rbx); |
// Push result (function). |
@@ -1230,7 +1190,7 @@ |
__ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
// Replace function on TOS with result in rax, or pop it. |
- DropAndMove(expr->context(), rax); |
+ DropAndApply(1, expr->context(), rax); |
} |
@@ -1260,10 +1220,10 @@ |
// Restore context register. |
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
// Discard the function left on TOS. |
- DropAndMove(expr->context(), rax); |
+ DropAndApply(1, expr->context(), rax); |
} else { |
__ CallRuntime(expr->function(), arg_count); |
- Move(expr->context(), rax); |
+ Apply(expr->context(), rax); |
} |
} |
@@ -1386,7 +1346,7 @@ |
} |
__ CallRuntime(Runtime::kTypeof, 1); |
- Move(expr->context(), rax); |
+ Apply(expr->context(), rax); |
break; |
} |
@@ -1486,7 +1446,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(), |
@@ -1503,10 +1463,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(), rax); |
+ DropAndApply(1, expr->context(), rax); |
} |
break; |
} |
@@ -1519,10 +1479,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(), rax, 2); |
+ DropAndApply(2, expr->context(), rax); |
} |
break; |
} |
@@ -1564,7 +1524,7 @@ |
NO_OVERWRITE, |
NO_GENERIC_BINARY_FLAGS); |
__ CallStub(&stub); |
- Move(expr->context(), rax); |
+ Apply(expr->context(), rax); |
break; |
} |
@@ -1732,7 +1692,7 @@ |
void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
__ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
- Move(expr->context(), rax); |
+ Apply(expr->context(), rax); |
} |