diff options
Diffstat (limited to 'deps/v8/src/arm/full-codegen-arm.cc')
-rw-r--r-- | deps/v8/src/arm/full-codegen-arm.cc | 182 |
1 files changed, 133 insertions, 49 deletions
diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc index 9f240dd82..489637380 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/deps/v8/src/arm/full-codegen-arm.cc @@ -52,12 +52,13 @@ namespace internal { // // The function builds a JS frame. Please see JavaScriptFrameConstants in // frames-arm.h for its layout. -void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { - function_ = fun; - SetFunctionPosition(fun); +void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) { + ASSERT(info_ == NULL); + info_ = info; + SetFunctionPosition(function()); if (mode == PRIMARY) { - int locals_count = fun->scope()->num_stack_slots(); + int locals_count = scope()->num_stack_slots(); __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); if (locals_count > 0) { @@ -77,7 +78,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { bool function_in_register = true; // Possibly allocate a local context. - if (fun->scope()->num_heap_slots() > 0) { + if (scope()->num_heap_slots() > 0) { Comment cmnt(masm_, "[ Allocate local context"); // Argument to NewContext is the function, which is in r1. __ push(r1); @@ -87,9 +88,9 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { // passed to us. It's saved in the stack and kept live in cp. __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); // Copy any necessary parameters into the context. - int num_parameters = fun->scope()->num_parameters(); + int num_parameters = scope()->num_parameters(); for (int i = 0; i < num_parameters; i++) { - Slot* slot = fun->scope()->parameter(i)->slot(); + Slot* slot = scope()->parameter(i)->slot(); if (slot != NULL && slot->type() == Slot::CONTEXT) { int parameter_offset = StandardFrameConstants::kCallerSPOffset + (num_parameters - 1 - i) * kPointerSize; @@ -107,7 +108,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { } } - Variable* arguments = fun->scope()->arguments()->AsVariable(); + Variable* arguments = scope()->arguments()->AsVariable(); if (arguments != NULL) { // Function uses arguments object. Comment cmnt(masm_, "[ Allocate arguments object"); @@ -118,9 +119,10 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { __ mov(r3, r1); } // Receiver is just before the parameters on the caller's stack. - __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset + - fun->num_parameters() * kPointerSize)); - __ mov(r1, Operand(Smi::FromInt(fun->num_parameters()))); + int offset = scope()->num_parameters() * kPointerSize; + __ add(r2, fp, + Operand(StandardFrameConstants::kCallerSPOffset + offset)); + __ mov(r1, Operand(Smi::FromInt(scope()->num_parameters()))); __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit()); // Arguments to ArgumentsAccessStub: @@ -133,7 +135,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { __ mov(r3, r0); Move(arguments->slot(), r0, r1, r2); Slot* dot_arguments_slot = - fun->scope()->arguments_shadow()->AsVariable()->slot(); + scope()->arguments_shadow()->AsVariable()->slot(); Move(dot_arguments_slot, r3, r1, r2); } } @@ -155,7 +157,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { } { Comment cmnt(masm_, "[ Declarations"); - VisitDeclarations(fun->scope()->declarations()); + VisitDeclarations(scope()->declarations()); } if (FLAG_trace) { @@ -164,7 +166,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { { Comment cmnt(masm_, "[ Body"); ASSERT(loop_depth() == 0); - VisitStatements(fun->body()); + VisitStatements(function()->body()); ASSERT(loop_depth() == 0); } @@ -173,7 +175,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { // body. __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); } - EmitReturnSequence(function_->end_position()); + EmitReturnSequence(function()->end_position()); } @@ -196,7 +198,7 @@ void FullCodeGenerator::EmitReturnSequence(int position) { // Calculate the exact length of the return sequence and make sure that // the constant pool is not emitted inside of the return sequence. - int num_parameters = function_->scope()->num_parameters(); + int num_parameters = scope()->num_parameters(); int32_t sp_delta = (num_parameters + 1) * kPointerSize; int return_sequence_length = Assembler::kJSReturnSequenceLength; if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) { @@ -512,7 +514,7 @@ MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { return MemOperand(fp, SlotOffset(slot)); case Slot::CONTEXT: { int context_chain_length = - function_->scope()->ContextChainLength(slot->var()->scope()); + scope()->ContextChainLength(slot->var()->scope()); __ LoadContext(scratch, context_chain_length); return CodeGenerator::ContextOperand(scratch, slot->index()); } @@ -572,7 +574,7 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) { // this specific context. // The variable in the decl always resides in the current context. - ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); + ASSERT_EQ(0, scope()->ContextChainLength(var->scope())); if (FLAG_debug_code) { // Check if we have the correct context pointer. __ ldr(r1, @@ -652,7 +654,7 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { // Call the runtime to declare the globals. // The context is the first argument. __ mov(r1, Operand(pairs)); - __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); + __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); __ CallRuntime(Runtime::kDeclareGlobals, 3); // Return value is ignored. @@ -664,7 +666,7 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { // Build the function boilerplate and instantiate it. Handle<JSFunction> boilerplate = - Compiler::BuildBoilerplate(expr, script_, this); + Compiler::BuildBoilerplate(expr, script(), this); if (HasStackOverflow()) return; ASSERT(boilerplate->IsBoilerplate()); @@ -814,9 +816,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { if (key->handle()->IsSymbol()) { VisitForValue(value, kAccumulator); __ mov(r2, Operand(key->handle())); + __ ldr(r1, MemOperand(sp)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); - // StoreIC leaves the receiver on the stack. break; } // Fall through. @@ -905,6 +907,92 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { } +void FullCodeGenerator::VisitAssignment(Assignment* expr) { + Comment cmnt(masm_, "[ Assignment"); + ASSERT(expr->op() != Token::INIT_CONST); + // Left-hand side can only be a property, a global or a (parameter or local) + // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. + enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; + LhsKind assign_type = VARIABLE; + Property* prop = expr->target()->AsProperty(); + if (prop != NULL) { + assign_type = + (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; + } + + // Evaluate LHS expression. + switch (assign_type) { + case VARIABLE: + // Nothing to do here. + break; + case NAMED_PROPERTY: + if (expr->is_compound()) { + // We need the receiver both on the stack and in the accumulator. + VisitForValue(prop->obj(), kAccumulator); + __ push(result_register()); + } else { + VisitForValue(prop->obj(), kStack); + } + break; + case KEYED_PROPERTY: + VisitForValue(prop->obj(), kStack); + VisitForValue(prop->key(), kStack); + break; + } + + // If we have a compound assignment: Get value of LHS expression and + // store in on top of the stack. + if (expr->is_compound()) { + Location saved_location = location_; + location_ = kStack; + switch (assign_type) { + case VARIABLE: + EmitVariableLoad(expr->target()->AsVariableProxy()->var(), + Expression::kValue); + break; + case NAMED_PROPERTY: + EmitNamedPropertyLoad(prop); + __ push(result_register()); + break; + case KEYED_PROPERTY: + EmitKeyedPropertyLoad(prop); + __ push(result_register()); + break; + } + location_ = saved_location; + } + + // Evaluate RHS expression. + Expression* rhs = expr->value(); + VisitForValue(rhs, kAccumulator); + + // If we have a compound assignment: Apply operator. + if (expr->is_compound()) { + Location saved_location = location_; + location_ = kAccumulator; + EmitBinaryOp(expr->binary_op(), Expression::kValue); + location_ = saved_location; + } + + // Record source position before possible IC call. + SetSourcePosition(expr->position()); + + // Store the value. + switch (assign_type) { + case VARIABLE: + EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), + context_); + break; + case NAMED_PROPERTY: + EmitNamedPropertyAssignment(expr); + break; + case KEYED_PROPERTY: + EmitKeyedPropertyAssignment(expr); + break; + } +} + + void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Literal* key = prop->key()->AsLiteral(); @@ -943,21 +1031,17 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, ASSERT(!var->is_this()); // Assignment to a global variable. Use inline caching for the // assignment. Right-hand-side value is passed in r0, variable name in - // r2, and the global object on the stack. + // r2, and the global object in r1. __ mov(r2, Operand(var->name())); - __ ldr(ip, CodeGenerator::GlobalObject()); - __ push(ip); + __ ldr(r1, CodeGenerator::GlobalObject()); 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. - DropAndApply(1, context, r0); } else if (slot != NULL && slot->type() == Slot::LOOKUP) { __ push(result_register()); // Value. __ mov(r1, Operand(var->name())); __ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name. __ CallRuntime(Runtime::kStoreContextSlot, 3); - Apply(context, r0); } else if (var->slot() != NULL) { Slot* slot = var->slot(); @@ -984,13 +1068,13 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, UNREACHABLE(); break; } - Apply(context, result_register()); } else { // Variables rewritten as properties are not treated as variables in // assignments. UNREACHABLE(); } + Apply(context, result_register()); } @@ -1014,6 +1098,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { // Record source code position before IC call. SetSourcePosition(expr->position()); __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); + if (expr->ends_initialization_block()) { + __ ldr(r1, MemOperand(sp)); + } else { + __ pop(r1); + } + Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); @@ -1024,9 +1114,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ push(ip); __ CallRuntime(Runtime::kToFastProperties, 1); __ pop(r0); + DropAndApply(1, context_, r0); + } else { + Apply(context_, r0); } - - DropAndApply(1, context_, r0); } @@ -1085,7 +1176,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) { } void FullCodeGenerator::EmitCallWithIC(Call* expr, - Handle<Object> ignored, + Handle<Object> name, RelocInfo::Mode mode) { // Code common for calls using the IC. ZoneList<Expression*>* args = expr->arguments(); @@ -1093,16 +1184,16 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, for (int i = 0; i < arg_count; i++) { VisitForValue(args->at(i), kStack); } + __ mov(r2, Operand(name)); // Record source position for debugger. SetSourcePosition(expr->position()); // Call the IC initialization code. - Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, - NOT_IN_LOOP); + InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; + Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); __ Call(ic, mode); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - // Discard the function left on TOS. - DropAndApply(1, context_, r0); + Apply(context_, r0); } @@ -1119,7 +1210,6 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) { __ CallStub(&stub); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - // Discard the function left on TOS. DropAndApply(1, context_, r0); } @@ -1133,11 +1223,9 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Call to the identifier 'eval'. UNREACHABLE(); } else if (var != NULL && !var->is_this() && var->is_global()) { - // Call to a global variable. - __ mov(r1, Operand(var->name())); - // Push global object as receiver for the call IC lookup. + // Push global object as receiver for the call IC. __ ldr(r0, CodeGenerator::GlobalObject()); - __ stm(db_w, sp, r1.bit() | r0.bit()); + __ push(r0); EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); } else if (var != NULL && var->slot() != NULL && var->slot()->type() == Slot::LOOKUP) { @@ -1149,8 +1237,6 @@ void FullCodeGenerator::VisitCall(Call* expr) { Literal* key = prop->key()->AsLiteral(); if (key != NULL && key->handle()->IsSymbol()) { // Call to a named property, use call IC. - __ mov(r0, Operand(key->handle())); - __ push(r0); VisitForValue(prop->obj(), kStack); EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); } else { @@ -1236,10 +1322,9 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { // Prepare for calling JS runtime function. - __ mov(r1, Operand(expr->name())); __ ldr(r0, CodeGenerator::GlobalObject()); __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); - __ stm(db_w, sp, r1.bit() | r0.bit()); + __ push(r0); } // Push the arguments ("left-to-right"). @@ -1250,18 +1335,17 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { // Call the JS runtime function. + __ mov(r2, Operand(expr->name())); Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, NOT_IN_LOOP); __ Call(ic, RelocInfo::CODE_TARGET); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - // Discard the function left on TOS. - DropAndApply(1, context_, r0); } else { // Call the C runtime function. __ CallRuntime(expr->function(), arg_count); - Apply(context_, r0); } + Apply(context_, r0); } @@ -1546,15 +1630,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { break; case NAMED_PROPERTY: { __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); + __ pop(r1); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); if (expr->is_postfix()) { - __ Drop(1); // Result is on the stack under the receiver. if (context_ != Expression::kEffect) { ApplyTOS(context_); } } else { - DropAndApply(1, context_, r0); + Apply(context_, r0); } break; } |