| Index: src/arm/fast-codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/fast-codegen-arm.cc (revision 3106)
|
| +++ src/arm/fast-codegen-arm.cc (working copy)
|
| @@ -29,6 +29,7 @@
|
|
|
| #include "codegen-inl.h"
|
| #include "fast-codegen.h"
|
| +#include "parser.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -110,11 +111,10 @@
|
|
|
| void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
| // Call the runtime to declare the globals.
|
| - __ mov(r0, Operand(pairs));
|
| - __ push(r0);
|
| - __ push(cp); // The context is the second argument.
|
| + // The context is the first argument.
|
| + __ mov(r1, Operand(pairs));
|
| __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0)));
|
| - __ push(r0);
|
| + __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit());
|
| __ CallRuntime(Runtime::kDeclareGlobals, 3);
|
| // Return value is ignored.
|
| }
|
| @@ -153,7 +153,7 @@
|
| __ RecordJSReturn();
|
| __ mov(sp, fp);
|
| __ ldm(ia_w, sp, fp.bit() | lr.bit());
|
| - int num_parameters = function_->scope()->num_parameters();
|
| + int num_parameters = function_->scope()->num_parameters();
|
| __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize));
|
| __ Jump(lr);
|
| }
|
| @@ -170,8 +170,7 @@
|
|
|
| // Create a new closure.
|
| __ mov(r0, Operand(boilerplate));
|
| - __ push(r0);
|
| - __ push(cp);
|
| + __ stm(db_w, sp, cp.bit() | r0.bit());
|
| __ CallRuntime(Runtime::kNewClosure, 2);
|
|
|
| if (expr->location().is_temporary()) {
|
| @@ -216,6 +215,79 @@
|
| }
|
|
|
|
|
| +void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
| + Comment cmnt(masm_, "[ ArrayLiteral");
|
| + Label make_clone;
|
| +
|
| + // Fetch the function's literals array.
|
| + __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
| + __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
|
| + // Check if the literal's boilerplate has been instantiated.
|
| + int offset =
|
| + FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize);
|
| + __ ldr(r0, FieldMemOperand(r3, offset));
|
| + __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
| + __ cmp(r0, ip);
|
| + __ b(&make_clone, ne);
|
| +
|
| + // Instantiate the boilerplate.
|
| + __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
|
| + __ mov(r1, Operand(expr->literals()));
|
| + __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit());
|
| + __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
|
| +
|
| + __ bind(&make_clone);
|
| + // Clone the boilerplate.
|
| + __ push(r0);
|
| + if (expr->depth() > 1) {
|
| + __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1);
|
| + } else {
|
| + __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1);
|
| + }
|
| +
|
| + bool result_saved = false; // Is the result saved to the stack?
|
| +
|
| + // Emit code to evaluate all the non-constant subexpressions and to store
|
| + // them into the newly cloned array.
|
| + ZoneList<Expression*>* subexprs = expr->values();
|
| + for (int i = 0, len = subexprs->length(); i < len; i++) {
|
| + Expression* subexpr = subexprs->at(i);
|
| + // If the subexpression is a literal or a simple materialized literal it
|
| + // is already set in the cloned array.
|
| + if (subexpr->AsLiteral() != NULL ||
|
| + CompileTimeValue::IsCompileTimeValue(subexpr)) {
|
| + continue;
|
| + }
|
| +
|
| + if (!result_saved) {
|
| + __ push(r0);
|
| + result_saved = true;
|
| + }
|
| + Visit(subexpr);
|
| + ASSERT(subexpr->location().is_temporary());
|
| +
|
| + // Store the subexpression value in the array's elements.
|
| + __ pop(r0); // Subexpression value.
|
| + __ ldr(r1, MemOperand(sp)); // Copy of array literal.
|
| + __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
|
| + int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
| + __ str(r0, FieldMemOperand(r1, offset));
|
| +
|
| + // Update the write barrier for the array store with r0 as the scratch
|
| + // register.
|
| + __ mov(r2, Operand(offset));
|
| + __ RecordWrite(r1, r2, r0);
|
| + }
|
| +
|
| + Location destination = expr->location();
|
| + if (destination.is_nowhere() && result_saved) {
|
| + __ pop();
|
| + } else if (destination.is_temporary() && !result_saved) {
|
| + __ push(r0);
|
| + }
|
| +}
|
| +
|
| +
|
| void FastCodeGenerator::VisitAssignment(Assignment* expr) {
|
| Comment cmnt(masm_, "[ Assignment");
|
| ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
|
| @@ -294,11 +366,10 @@
|
| ASSERT(var != NULL && !var->is_this() && var->is_global());
|
| ASSERT(!var->is_possibly_eval());
|
|
|
| - __ mov(r0, Operand(var->name()));
|
| - __ push(r0);
|
| - // Push global object (receiver)
|
| + __ mov(r1, Operand(var->name()));
|
| + // Push global object as receiver.
|
| __ ldr(r0, CodeGenerator::GlobalObject());
|
| - __ push(r0);
|
| + __ stm(db_w, sp, r1.bit() | r0.bit());
|
| int arg_count = args->length();
|
| for (int i = 0; i < arg_count; i++) {
|
| Visit(args->at(i));
|
|
|