diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index f773664284..5cda172fce 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -614,15 +614,7 @@ void CodeGenerator::LoadReference(Reference* ref) { // The expression is either a property or a variable proxy that rewrites // to a property. LoadAndSpill(property->obj()); - // We use a named reference if the key is a literal symbol, unless it is - // a string that can be legally parsed as an integer. This is because - // otherwise we will not get into the slow case code that handles [] on - // String objects. - Literal* literal = property->key()->AsLiteral(); - uint32_t dummy; - if (literal != NULL && - literal->handle()->IsSymbol() && - !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { + if (property->key()->IsPropertyName()) { ref->set_type(Reference::NAMED); } else { LoadAndSpill(property->key()); diff --git a/src/arm/fast-codegen-arm.cc b/src/arm/fast-codegen-arm.cc index bc406fd3b0..27bdd0fc7b 100644 --- a/src/arm/fast-codegen-arm.cc +++ b/src/arm/fast-codegen-arm.cc @@ -214,40 +214,43 @@ void FastCodeGenerator::EmitReturnSequence(int position) { } -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: - __ push(source); - break; case Expression::kTest: - TestAndBranch(source, true_label_, false_label_); + case Expression::kValueTest: + case Expression::kTestValue: + Move(scratch, slot); + Apply(context, scratch); break; - case Expression::kValueTest: { - Label discard; - __ push(source); - TestAndBranch(source, true_label_, &discard); - __ bind(&discard); - __ pop(); - __ jmp(false_label_); - break; - } - case Expression::kTestValue: { - Label discard; - __ push(source); - TestAndBranch(source, &discard, false_label_); - __ bind(&discard); - __ pop(); - __ jmp(true_label_); - } } } -void FastCodeGenerator::MoveTOS(Expression::Context context) { +void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { + switch (context) { + case Expression::kUninitialized: + UNREACHABLE(); + case Expression::kEffect: + break; + case Expression::kValue: + case Expression::kTest: + case Expression::kValueTest: + case Expression::kTestValue: + __ mov(ip, Operand(lit->handle())); + Apply(context, ip); + break; + } +} + + +void FastCodeGenerator::ApplyTOS(Expression::Context context) { switch (context) { case Expression::kUninitialized: UNREACHABLE(); @@ -281,6 +284,49 @@ void FastCodeGenerator::MoveTOS(Expression::Context context) { } +void FastCodeGenerator::DropAndApply(int count, + Expression::Context context, + Register reg) { + ASSERT(count > 0); + ASSERT(!reg.is(sp)); + switch (context) { + case Expression::kUninitialized: + UNREACHABLE(); + case Expression::kEffect: + __ Drop(count); + break; + case Expression::kValue: + if (count > 1) __ Drop(count - 1); + __ str(reg, MemOperand(sp)); + break; + case Expression::kTest: + __ Drop(count); + TestAndBranch(reg, true_label_, false_label_); + break; + case Expression::kValueTest: { + Label discard; + if (count > 1) __ Drop(count - 1); + __ str(reg, MemOperand(sp)); + TestAndBranch(reg, true_label_, &discard); + __ bind(&discard); + __ Drop(1); + __ jmp(false_label_); + break; + } + case Expression::kTestValue: { + Label discard; + if (count > 1) __ Drop(count - 1); + __ str(reg, MemOperand(sp)); + TestAndBranch(reg, &discard, false_label_); + __ bind(&discard); + __ Drop(1); + __ jmp(true_label_); + break; + } + } +} + + MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { switch (slot->type()) { case Slot::PARAMETER: @@ -308,42 +354,6 @@ void FastCodeGenerator::Move(Register destination, Slot* source) { -void FastCodeGenerator::Move(Expression::Context context, - Slot* source, - Register scratch) { - switch (context) { - case Expression::kUninitialized: - UNREACHABLE(); - case Expression::kEffect: - break; - case Expression::kValue: - 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: - case Expression::kTest: - case Expression::kValueTest: - case Expression::kTestValue: - __ mov(ip, Operand(expr->handle())); - Move(context, ip); - break; - } -} - - void FastCodeGenerator::Move(Slot* dst, Register src, Register scratch1, @@ -361,55 +371,6 @@ void FastCodeGenerator::Move(Slot* dst, -void FastCodeGenerator::DropAndMove(Expression::Context context, - Register source, - int drop_count) { - ASSERT(drop_count > 0); - switch (context) { - case Expression::kUninitialized: - UNREACHABLE(); - case Expression::kEffect: - __ add(sp, sp, Operand(drop_count * kPointerSize)); - break; - case Expression::kValue: - if (drop_count > 1) { - __ add(sp, sp, Operand((drop_count - 1) * kPointerSize)); - } - __ str(source, MemOperand(sp)); - break; - case Expression::kTest: - ASSERT(!source.is(sp)); - __ add(sp, sp, Operand(drop_count * kPointerSize)); - TestAndBranch(source, true_label_, false_label_); - break; - case Expression::kValueTest: { - Label discard; - if (drop_count > 1) { - __ add(sp, sp, Operand((drop_count - 1) * kPointerSize)); - } - __ str(source, MemOperand(sp)); - TestAndBranch(source, true_label_, &discard); - __ bind(&discard); - __ pop(); - __ jmp(false_label_); - break; - } - case Expression::kTestValue: { - Label discard; - if (drop_count > 1) { - __ add(sp, sp, Operand((drop_count - 1) * kPointerSize)); - } - __ str(source, MemOperand(sp)); - TestAndBranch(source, &discard, false_label_); - __ bind(&discard); - __ pop(); - __ jmp(true_label_); - break; - } - } -} - - void FastCodeGenerator::TestAndBranch(Register source, Label* true_label, Label* false_label) { @@ -524,7 +485,7 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) { // Value in r0 is ignored (declarations are statements). Receiver // and key on stack are discarded. - __ add(sp, sp, Operand(2 * kPointerSize)); + __ Drop(2); } } } @@ -555,7 +516,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { __ mov(r0, Operand(boilerplate)); __ stm(db_w, sp, cp.bit() | r0.bit()); __ CallRuntime(Runtime::kNewClosure, 2); - Move(expr->context(), r0); + Apply(expr->context(), r0); } @@ -578,7 +539,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var, __ mov(r2, Operand(var->name())); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); - DropAndMove(context, r0); + DropAndApply(1, context, r0); } else if (rewrite->AsSlot() != NULL) { Slot* slot = rewrite->AsSlot(); if (FLAG_debug_code) { @@ -597,17 +558,18 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var, break; } } - Move(context, slot, r0); + Apply(context, slot, r0); } 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_var = property->obj()->AsVariableProxy()->AsVariable(); ASSERT_NOT_NULL(object_var); Slot* object_slot = object_var->slot(); @@ -616,7 +578,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var, // Load the object. Move(r2, object_slot); - // 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()); @@ -627,12 +589,12 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var, // Push both as arguments to ic. __ stm(db_w, sp, r2.bit() | r1.bit()); - // Do a KEYED property load. + // Do a keyed property load. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); // Drop key and object left on the stack by IC, and push the result. - DropAndMove(context, r0, 2); + DropAndApply(2, context, r0); } } @@ -660,7 +622,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); __ bind(&done); - Move(expr->context(), r0); + Apply(expr->context(), r0); } @@ -742,7 +704,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { case Expression::kUninitialized: UNREACHABLE(); case Expression::kEffect: - if (result_saved) __ pop(); + if (result_saved) __ Drop(1); break; case Expression::kValue: if (!result_saved) __ push(r0); @@ -756,7 +718,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { if (!result_saved) __ push(r0); TestAndBranch(r0, true_label_, &discard); __ bind(&discard); - __ pop(); + __ Drop(1); __ jmp(false_label_); break; } @@ -765,7 +727,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { if (!result_saved) __ push(r0); TestAndBranch(r0, &discard, false_label_); __ bind(&discard); - __ pop(); + __ Drop(1); __ jmp(true_label_); break; } @@ -824,7 +786,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { case Expression::kUninitialized: UNREACHABLE(); case Expression::kEffect: - if (result_saved) __ pop(); + if (result_saved) __ Drop(1); break; case Expression::kValue: if (!result_saved) __ push(r0); @@ -838,7 +800,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { if (!result_saved) __ push(r0); TestAndBranch(r0, true_label_, &discard); __ bind(&discard); - __ pop(); + __ Drop(1); __ jmp(false_label_); break; } @@ -847,7 +809,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { if (!result_saved) __ push(r0); TestAndBranch(r0, &discard, false_label_); __ bind(&discard); - __ pop(); + __ Drop(1); __ jmp(true_label_); break; } @@ -862,7 +824,7 @@ void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, __ mov(r2, Operand(key->handle())); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); - Move(context, r0); + Apply(context, r0); } @@ -871,7 +833,7 @@ void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, SetSourcePosition(prop->position()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); - Move(context, r0); + Apply(context, r0); } @@ -882,7 +844,7 @@ void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, GenericBinaryOpStub stub(op, NO_OVERWRITE); __ CallStub(&stub); - Move(context, r0); + Apply(context, r0); } @@ -901,7 +863,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, Handle 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, r0); + DropAndApply(1, context, r0); } else if (var->slot() != NULL) { Slot* slot = var->slot(); @@ -934,7 +896,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, __ str(r0, target); TestAndBranch(r0, true_label_, &discard); __ bind(&discard); - __ pop(); + __ Drop(1); __ jmp(false_label_); break; } @@ -944,7 +906,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, __ str(r0, target); TestAndBranch(r0, &discard, false_label_); __ bind(&discard); - __ pop(); + __ Drop(1); __ jmp(true_label_); break; } @@ -976,7 +938,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, __ RecordWrite(r1, r2, r0); __ bind(&exit); if (context != Expression::kEffect && context != Expression::kValue) { - Move(context, r3); + Apply(context, r3); } break; } @@ -1022,7 +984,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ pop(r0); } - DropAndMove(expr->context(), r0); + DropAndApply(1, expr->context(), r0); } @@ -1054,15 +1016,13 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { } // Receiver and key are still on stack. - __ add(sp, sp, Operand(2 * kPointerSize)); - Move(expr->context(), r0); + DropAndApply(2, expr->context(), r0); } 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()); @@ -1070,22 +1030,21 @@ void FastCodeGenerator::VisitProperty(Property* expr) { // 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 r2 and the receiver on the stack. + if (key->IsPropertyName()) { + // Do a named property load. The IC expects the property name in r2 and + // the receiver on the stack. __ mov(r2, Operand(key->AsLiteral()->handle())); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); + DropAndApply(1, expr->context(), r0); } else { - // Do a KEYED property load. + // Do a keyed property load. Visit(expr->key()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); // Drop key and receiver left on the stack by IC. - __ pop(); + DropAndApply(2, expr->context(), r0); } - DropAndMove(expr->context(), r0); } void FastCodeGenerator::EmitCallWithIC(Call* expr, @@ -1107,7 +1066,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr, // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); // Discard the function left on TOS. - DropAndMove(expr->context(), r0); + DropAndApply(1, expr->context(), r0); } @@ -1125,7 +1084,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) { // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); // Discard the function left on TOS. - DropAndMove(expr->context(), r0); + DropAndApply(1, expr->context(), r0); } @@ -1234,7 +1193,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) { __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); // Replace function on TOS with result in r0, or pop it. - DropAndMove(expr->context(), r0); + DropAndApply(1, expr->context(), r0); } @@ -1265,11 +1224,11 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); // Discard the function left on TOS. - DropAndMove(expr->context(), r0); + DropAndApply(1, expr->context(), r0); } else { // Call the C runtime function. __ CallRuntime(expr->function(), arg_count); - Move(expr->context(), r0); + Apply(expr->context(), r0); } } @@ -1398,7 +1357,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { } __ CallRuntime(Runtime::kTypeof, 1); - Move(expr->context(), r0); + Apply(expr->context(), r0); break; } @@ -1499,7 +1458,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { // 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(), @@ -1513,10 +1472,10 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 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(), r0); + DropAndApply(1, expr->context(), r0); } break; } @@ -1526,10 +1485,10 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 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(), r0, 2); + DropAndApply(2, expr->context(), r0); } break; } @@ -1573,7 +1532,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { GenericBinaryOpStub stub(expr->op(), NO_OVERWRITE); __ CallStub(&stub); - Move(expr->context(), r0); + Apply(expr->context(), r0); break; } @@ -1748,7 +1707,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); - Move(expr->context(), r0); + Apply(expr->context(), r0); } diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 876eec109c..18cadaca3b 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -162,9 +162,9 @@ void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) { } -void MacroAssembler::Drop(int stack_elements, Condition cond) { - if (stack_elements > 0) { - add(sp, sp, Operand(stack_elements * kPointerSize), LeaveCC, cond); +void MacroAssembler::Drop(int count, Condition cond) { + if (count > 0) { + add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond); } } diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 88bfa9ce0a..8f2064a745 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -64,7 +64,11 @@ class MacroAssembler: public Assembler { void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al); void Call(Handle code, RelocInfo::Mode rmode, Condition cond = al); void Ret(Condition cond = al); - void Drop(int stack_elements, Condition cond = al); + + // Emit code to discard a non-negative number of pointer-sized elements + // from the stack, clobbering only the sp register. + void Drop(int count, Condition cond = al); + void Call(Label* target); void Move(Register dst, Handle value); // Jumps to the label at the index given by the Smi in "index". diff --git a/src/ast.h b/src/ast.h index 5d2a8b6382..ec32318114 100644 --- a/src/ast.h +++ b/src/ast.h @@ -187,6 +187,11 @@ class Expression: public AstNode { virtual bool IsValidJSON() { return false; } virtual bool IsValidLeftHandSide() { return false; } + // Symbols that cannot be parsed as array indices are considered property + // names. We do not treat symbols that can be array indexes as property + // names because [] for string objects is handled only by keyed ICs. + virtual bool IsPropertyName() { return false; } + // Mark the expression as being compiled as an expression // statement. This is used to transform postfix increments to // (faster) prefix increments. @@ -707,6 +712,14 @@ class Literal: public Expression { virtual bool IsValidJSON() { return true; } + virtual bool IsPropertyName() { + if (handle_->IsSymbol()) { + uint32_t ignored; + return !String::cast(*handle_)->AsArrayIndex(&ignored); + } + return false; + } + // Identity testers. bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); } bool IsTrue() const { return handle_.is_identical_to(Factory::true_value()); } diff --git a/src/compiler.cc b/src/compiler.cc index 87cbefa220..519362c566 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -902,11 +902,7 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) { // We will only visit the key during code generation for keyed property // stores. Leave its expression context uninitialized for named // property stores. - Literal* lit = prop->key()->AsLiteral(); - uint32_t ignored; - if (lit == NULL || - !lit->handle()->IsSymbol() || - String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) { + if (!prop->key()->IsPropertyName()) { ProcessExpression(prop->key(), Expression::kValue); CHECK_BAILOUT; } @@ -1030,11 +1026,7 @@ void CodeGenSelector::VisitCountOperation(CountOperation* expr) { // We will only visit the key during code generation for keyed property // stores. Leave its expression context uninitialized for named // property stores. - Literal* lit = prop->key()->AsLiteral(); - uint32_t ignored; - if (lit == NULL || - !lit->handle()->IsSymbol() || - String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) { + if (!prop->key()->IsPropertyName()) { ProcessExpression(prop->key(), Expression::kValue); CHECK_BAILOUT; } diff --git a/src/fast-codegen.cc b/src/fast-codegen.cc index 83714f0522..a76ae9ca36 100644 --- a/src/fast-codegen.cc +++ b/src/fast-codegen.cc @@ -75,6 +75,39 @@ int FastCodeGenerator::SlotOffset(Slot* slot) { } +void FastCodeGenerator::Apply(Expression::Context context, Register reg) { + switch (context) { + case Expression::kUninitialized: + UNREACHABLE(); + case Expression::kEffect: + break; + case Expression::kValue: + __ push(reg); + break; + case Expression::kTest: + TestAndBranch(reg, true_label_, false_label_); + break; + case Expression::kValueTest: { + Label discard; + __ push(reg); + TestAndBranch(reg, true_label_, &discard); + __ bind(&discard); + __ Drop(1); + __ jmp(false_label_); + break; + } + case Expression::kTestValue: { + Label discard; + __ push(reg); + TestAndBranch(reg, &discard, false_label_); + __ bind(&discard); + __ Drop(1); + __ jmp(true_label_); + } + } +} + + void FastCodeGenerator::VisitDeclarations( ZoneList* declarations) { int length = declarations->length(); @@ -624,7 +657,7 @@ void FastCodeGenerator::VisitSlot(Slot* expr) { void FastCodeGenerator::VisitLiteral(Literal* expr) { Comment cmnt(masm_, "[ Literal"); - Move(expr->context(), expr); + Apply(expr->context(), expr); } diff --git a/src/fast-codegen.h b/src/fast-codegen.h index 6fbce65b32..74c9b4d1bc 100644 --- a/src/fast-codegen.h +++ b/src/fast-codegen.h @@ -212,10 +212,23 @@ class FastCodeGenerator: public AstVisitor { int SlotOffset(Slot* slot); - void Move(Expression::Context destination, Register source); - void MoveTOS(Expression::Context destination); - void Move(Expression::Context destination, Slot* source, Register scratch); - void Move(Expression::Context destination, Literal* source); + + // Emit code to complete the evaluation of an expression based on its + // expression context and given its value is in a register, non-lookup + // slot, or a literal. + void Apply(Expression::Context context, Register reg); + void Apply(Expression::Context context, Slot* slot, Register scratch); + void Apply(Expression::Context context, Literal* lit); + + // Emit code to complete the evaluation of an expression based on its + // expression context and given its value is on top of the stack. + void ApplyTOS(Expression::Context context); + + // Emit code to discard count elements from the top of stack, then + // complete the evaluation of an expression based on its expression + // context and given its value is in a register. + void DropAndApply(int count, Expression::Context context, Register reg); + void Move(Slot* dst, Register source, Register scratch1, Register scratch2); void Move(Register dst, Slot* source); @@ -224,12 +237,6 @@ class FastCodeGenerator: public AstVisitor { // register. MemOperand EmitSlotSearch(Slot* slot, Register scratch); - // Drop the TOS, and store source to destination. - // If destination is TOS, just overwrite TOS with source. - void DropAndMove(Expression::Context destination, - Register source, - int drop_count = 1); - // Test the JavaScript value in source as if in a test context, compile // control flow to a pair of labels. void TestAndBranch(Register source, Label* true_label, Label* false_label); diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index ff26956564..819231a43b 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -664,15 +664,7 @@ void CodeGenerator::LoadReference(Reference* ref) { // The expression is either a property or a variable proxy that rewrites // to a property. Load(property->obj()); - // We use a named reference if the key is a literal symbol, unless it is - // a string that can be legally parsed as an integer. This is because - // otherwise we will not get into the slow case code that handles [] on - // String objects. - Literal* literal = property->key()->AsLiteral(); - uint32_t dummy; - if (literal != NULL && - literal->handle()->IsSymbol() && - !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { + if (property->key()->IsPropertyName()) { ref->set_type(Reference::NAMED); } else { Load(property->key()); diff --git a/src/ia32/fast-codegen-ia32.cc b/src/ia32/fast-codegen-ia32.cc index ea91d5240e..ddb6d0b9a3 100644 --- a/src/ia32/fast-codegen-ia32.cc +++ b/src/ia32/fast-codegen-ia32.cc @@ -194,40 +194,49 @@ void FastCodeGenerator::EmitReturnSequence(int position) { } -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(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; - case Expression::kValueTest: { - Label discard; - __ push(source); - TestAndBranch(source, true_label_, &discard); - __ bind(&discard); - __ add(Operand(esp), Immediate(kPointerSize)); - __ jmp(false_label_); - break; - } - case Expression::kTestValue: { - Label discard; - __ push(source); - TestAndBranch(source, &discard, false_label_); - __ bind(&discard); - __ add(Operand(esp), Immediate(kPointerSize)); - __ jmp(true_label_); - } } } -void FastCodeGenerator::MoveTOS(Expression::Context context) { +void FastCodeGenerator::ApplyTOS(Expression::Context context) { switch (context) { case Expression::kUninitialized: UNREACHABLE(); @@ -261,6 +270,49 @@ void FastCodeGenerator::MoveTOS(Expression::Context context) { } +void FastCodeGenerator::DropAndApply(int count, + Expression::Context context, + Register reg) { + ASSERT(count > 0); + ASSERT(!reg.is(esp)); + switch (context) { + case Expression::kUninitialized: + UNREACHABLE(); + case Expression::kEffect: + __ Drop(count); + break; + case Expression::kValue: + if (count > 1) __ Drop(count - 1); + __ mov(Operand(esp, 0), reg); + break; + case Expression::kTest: + __ Drop(count); + TestAndBranch(reg, true_label_, false_label_); + break; + case Expression::kValueTest: { + 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_); + break; + } + case Expression::kTestValue: { + Label discard; + if (count > 1) __ Drop(count - 1); + __ mov(Operand(esp, 0), reg); + TestAndBranch(reg, &discard, false_label_); + __ bind(&discard); + __ Drop(1); + __ jmp(true_label_); + break; + } + } +} + + MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { switch (slot->type()) { case Slot::PARAMETER: @@ -286,48 +338,6 @@ void FastCodeGenerator::Move(Register destination, Slot* source) { } -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::Move(Slot* dst, } -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 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) { // 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 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { __ push(esi); __ push(Immediate(boilerplate)); __ CallRuntime(Runtime::kNewClosure, 2); - Move(expr->context(), eax); + Apply(expr->context(), eax); } @@ -575,7 +536,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var, // 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 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var, 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 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(); // Drop key and object left on the stack by IC. - DropAndMove(context, eax, 2); + DropAndApply(2, context, eax); } } @@ -657,7 +619,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); // Label done: __ bind(&done); - Move(expr->context(), eax); + Apply(expr->context(), eax); } @@ -733,7 +695,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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 @@ void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, __ mov(ecx, Immediate(key->handle())); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); - Move(context, eax); + Apply(context, eax); } @@ -859,7 +821,7 @@ void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, SetSourcePosition(prop->position()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); - Move(context, eax); + Apply(context, eax); } @@ -869,7 +831,7 @@ void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, NO_OVERWRITE, NO_GENERIC_BINARY_FLAGS); __ CallStub(&stub); - Move(context, eax); + Apply(context, eax); } @@ -887,7 +849,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, Handle 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 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, __ 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 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, __ 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 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, } 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 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ pop(eax); } - DropAndMove(expr->context(), eax); + DropAndApply(1, expr->context(), eax); } @@ -1029,34 +990,32 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { } // 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 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 ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); @@ -1064,9 +1023,8 @@ void FastCodeGenerator::VisitProperty(Property* expr) { // 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 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr, __ call(ic, mode); // Restore context register. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - Move(expr->context(), eax); + Apply(expr->context(), eax); } @@ -1105,7 +1063,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) { __ CallStub(&stub); // Restore context register. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - DropAndMove(expr->context(), eax); + DropAndApply(1, expr->context(), eax); } @@ -1146,7 +1104,7 @@ void FastCodeGenerator::VisitCall(Call* expr) { // 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 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) { __ 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 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { // Call the C runtime function. __ CallRuntime(expr->function(), arg_count); } - Move(expr->context(), eax); + Apply(expr->context(), eax); } @@ -1369,7 +1327,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { } __ CallRuntime(Runtime::kTypeof, 1); - Move(expr->context(), eax); + Apply(expr->context(), eax); break; } @@ -1469,7 +1427,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { // 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 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 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 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 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 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { NO_OVERWRITE, NO_GENERIC_BINARY_FLAGS); __ CallStub(&stub); - Move(expr->context(), eax); + Apply(expr->context(), eax); break; } @@ -1719,7 +1677,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); - Move(expr->context(), eax); + Apply(expr->context(), eax); } diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index c78c76950c..ceecebf707 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -368,6 +368,8 @@ class MacroAssembler: public Assembler { void Ret(); + // Emit code to discard a non-negative number of pointer-sized elements + // from the stack, clobbering only the esp register. void Drop(int element_count); void Call(Label* target) { call(target); } diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 73ebc30ea0..904d02d4f8 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -4256,15 +4256,7 @@ void CodeGenerator::LoadReference(Reference* ref) { // The expression is either a property or a variable proxy that rewrites // to a property. Load(property->obj()); - // We use a named reference if the key is a literal symbol, unless it is - // a string that can be legally parsed as an integer. This is because - // otherwise we will not get into the slow case code that handles [] on - // String objects. - Literal* literal = property->key()->AsLiteral(); - uint32_t dummy; - if (literal != NULL && - literal->handle()->IsSymbol() && - !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { + if (property->key()->IsPropertyName()) { ref->set_type(Reference::NAMED); } else { Load(property->key()); diff --git a/src/x64/fast-codegen-x64.cc b/src/x64/fast-codegen-x64.cc index a9940bb3f8..fea0cdbc69 100644 --- a/src/x64/fast-codegen-x64.cc +++ b/src/x64/fast-codegen-x64.cc @@ -202,41 +202,49 @@ void FastCodeGenerator::EmitReturnSequence(int position) { } -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; - case Expression::kValueTest: { - Label discard; - __ push(source); - TestAndBranch(source, true_label_, &discard); - __ bind(&discard); - __ addq(rsp, Immediate(kPointerSize)); - __ jmp(false_label_); - break; - } - case Expression::kTestValue: { - Label discard; - __ push(source); - TestAndBranch(source, &discard, false_label_); - __ bind(&discard); - __ addq(rsp, Immediate(kPointerSize)); - __ jmp(true_label_); - break; - } } } -void FastCodeGenerator::MoveTOS(Expression::Context context) { +void FastCodeGenerator::ApplyTOS(Expression::Context context) { switch (context) { case Expression::kUninitialized: UNREACHABLE(); @@ -270,6 +278,49 @@ 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(count); + break; + case Expression::kValue: + if (count > 1) __ Drop(count - 1); + __ movq(Operand(rsp, 0), reg); + break; + case Expression::kTest: + __ Drop(count); + TestAndBranch(reg, true_label_, false_label_); + break; + case Expression::kValueTest: { + 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_); + break; + } + case Expression::kTestValue: { + Label discard; + if (count > 1) __ Drop(count - 1); + __ movq(Operand(rsp, 0), reg); + TestAndBranch(reg, &discard, false_label_); + __ bind(&discard); + __ Drop(1); + __ jmp(true_label_); + break; + } + } +} + + MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { switch (slot->type()) { case Slot::PARAMETER: @@ -295,48 +346,6 @@ void FastCodeGenerator::Move(Register destination, Slot* source) { } -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::Move(Slot* dst, } -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 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) { // 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 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { __ push(rsi); __ Push(boilerplate); __ CallRuntime(Runtime::kNewClosure, 2); - Move(expr->context(), rax); + Apply(expr->context(), rax); } @@ -585,7 +548,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var, // 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 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var, 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 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 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); // Label done: __ bind(&done); - Move(expr->context(), rax); + Apply(expr->context(), rax); } @@ -742,7 +707,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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 @@ void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, __ Move(rcx, key->handle()); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); - Move(context, rax); + Apply(context, rax); } @@ -868,7 +833,7 @@ void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, SetSourcePosition(prop->position()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); - Move(context, rax); + Apply(context, rax); } @@ -878,7 +843,7 @@ void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, NO_OVERWRITE, NO_GENERIC_BINARY_FLAGS); __ CallStub(&stub); - Move(context, rax); + Apply(context, rax); } @@ -896,7 +861,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, Handle 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 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, __ movq(target, rax); TestAndBranch(rax, true_label_, &discard); __ bind(&discard); - __ addq(rsp, Immediate(kPointerSize)); + __ Drop(1); __ jmp(false_label_); break; } @@ -938,7 +903,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, __ movq(target, rax); TestAndBranch(rax, &discard, false_label_); __ bind(&discard); - __ addq(rsp, Immediate(kPointerSize)); + __ Drop(1); __ jmp(true_label_); break; } @@ -959,9 +924,8 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var, } 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 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ pop(rax); } - DropAndMove(expr->context(), rax); + DropAndApply(1, expr->context(), rax); } @@ -1038,15 +1002,13 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { } // 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 @@ void FastCodeGenerator::VisitProperty(Property* expr) { // 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 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 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 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr, // 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 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) { // 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 @@ void FastCodeGenerator::VisitCall(Call* expr) { // 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 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) { __ 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 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { // 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 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { } __ CallRuntime(Runtime::kTypeof, 1); - Move(expr->context(), rax); + Apply(expr->context(), rax); break; } @@ -1486,7 +1446,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { // 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 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 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 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 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 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { NO_OVERWRITE, NO_GENERIC_BINARY_FLAGS); __ CallStub(&stub); - Move(expr->context(), rax); + Apply(expr->context(), rax); break; } @@ -1732,7 +1692,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); - Move(expr->context(), rax); + Apply(expr->context(), rax); } diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index 24b3037557..37f96a66ff 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -415,7 +415,11 @@ class MacroAssembler: public Assembler { void Cmp(Register dst, Handle source); void Cmp(const Operand& dst, Handle source); void Push(Handle source); + + // Emit code to discard a non-negative number of pointer-sized elements + // from the stack, clobbering only the rsp register. void Drop(int stack_elements); + void Call(Label* target) { call(target); } // Control Flow