| Index: src/arm/full-codegen-arm.cc
|
| diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
|
| index c57c78559803c81e51137a32876688dff0ceebc0..1ee612b5325e2a51e55ba6ed398b9d1ab14b6184 100644
|
| --- a/src/arm/full-codegen-arm.cc
|
| +++ b/src/arm/full-codegen-arm.cc
|
| @@ -168,9 +168,20 @@ void FullCodeGenerator::Generate() {
|
| // Generators allocate locals, if any, in context slots.
|
| ASSERT(!info->function()->is_generator() || locals_count == 0);
|
| if (locals_count > 0) {
|
| - __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
| - for (int i = 0; i < locals_count; i++) {
|
| - __ push(ip);
|
| + // Emit a loop to initialize stack cells for locals when optimizing for
|
| + // size. Otherwise, unroll the loop for maximum performance.
|
| + __ LoadRoot(r9, Heap::kUndefinedValueRootIndex);
|
| + if (FLAG_optimize_for_size && locals_count > 4) {
|
| + Label loop;
|
| + __ mov(r2, Operand(locals_count));
|
| + __ bind(&loop);
|
| + __ sub(r2, r2, Operand(1), SetCC);
|
| + __ push(r9);
|
| + __ b(&loop, ne);
|
| + } else {
|
| + for (int i = 0; i < locals_count; i++) {
|
| + __ push(r9);
|
| + }
|
| }
|
| }
|
| }
|
| @@ -613,12 +624,11 @@ void FullCodeGenerator::StackValueContext::Plug(
|
| Label done;
|
| __ bind(materialize_true);
|
| __ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
| - __ push(ip);
|
| __ jmp(&done);
|
| __ bind(materialize_false);
|
| __ LoadRoot(ip, Heap::kFalseValueRootIndex);
|
| - __ push(ip);
|
| __ bind(&done);
|
| + __ push(ip);
|
| }
|
|
|
|
|
| @@ -1597,9 +1607,8 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
| __ jmp(&allocated);
|
|
|
| __ bind(&runtime_allocate);
|
| - __ push(r5);
|
| __ mov(r0, Operand(Smi::FromInt(size)));
|
| - __ push(r0);
|
| + __ Push(r5, r0);
|
| __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
|
| __ pop(r5);
|
|
|
| @@ -1781,13 +1790,11 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
| __ CallStub(&stub);
|
| __ IncrementCounter(
|
| isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2);
|
| - } else if (expr->depth() > 1) {
|
| + } else if (expr->depth() > 1 ||
|
| + Serializer::enabled() ||
|
| + length > FastCloneShallowArrayStub::kMaximumClonedLength) {
|
| __ Push(r3, r2, r1);
|
| __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
|
| - } else if (Serializer::enabled() ||
|
| - length > FastCloneShallowArrayStub::kMaximumClonedLength) {
|
| - __ Push(r3, r2, r1);
|
| - __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
|
| } else {
|
| ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
|
| FLAG_smi_only_arrays);
|
| @@ -2036,8 +2043,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
| handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
|
| __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw"
|
| __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
|
| - __ push(r3); // iter
|
| - __ push(r0); // exception
|
| + __ Push(r3, r0); // iter, exception
|
| __ jmp(&l_call);
|
|
|
| // try { received = %yield result }
|
| @@ -2073,8 +2079,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
| __ bind(&l_next);
|
| __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next"
|
| __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
|
| - __ push(r3); // iter
|
| - __ push(r0); // received
|
| + __ Push(r3, r0); // iter, received
|
|
|
| // result = receiver[f](arg);
|
| __ bind(&l_call);
|
| @@ -2150,11 +2155,13 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
|
| __ bl(&resume_frame);
|
| __ jmp(&done);
|
| __ bind(&resume_frame);
|
| - __ push(lr); // Return address.
|
| - __ push(fp); // Caller's frame pointer.
|
| - __ mov(fp, sp);
|
| - __ push(cp); // Callee's context.
|
| - __ push(r4); // Callee's JS Function.
|
| + // lr = return address.
|
| + // fp = caller's frame pointer.
|
| + // cp = callee's context,
|
| + // r4 = callee's JS function.
|
| + __ Push(lr, fp, cp, r4);
|
| + // Adjust FP to point to saved FP.
|
| + __ add(fp, sp, Operand(2 * kPointerSize));
|
|
|
| // Load the operand stack size.
|
| __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
|
| @@ -2186,8 +2193,8 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
|
| __ push(r2);
|
| __ b(&push_operand_holes);
|
| __ bind(&call_resume);
|
| - __ push(r1);
|
| - __ push(result_register());
|
| + ASSERT(!result_register().is(r1));
|
| + __ Push(r1, result_register());
|
| __ Push(Smi::FromInt(resume_mode));
|
| __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
|
| // Not reached: the runtime call returns elsewhere.
|
| @@ -2409,8 +2416,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
|
| VisitForStackValue(prop->obj());
|
| VisitForAccumulatorValue(prop->key());
|
| __ mov(r1, r0);
|
| - __ pop(r2);
|
| - __ pop(r0); // Restore value.
|
| + __ Pop(r0, r2); // r0 = restored value.
|
| Handle<Code> ic = is_classic_mode()
|
| ? isolate()->builtins()->KeyedStoreIC_Initialize()
|
| : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
| @@ -2544,8 +2550,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
|
|
| // Record source code position before IC call.
|
| SetSourcePosition(expr->position());
|
| - __ pop(r1); // Key.
|
| - __ pop(r2);
|
| + __ Pop(r2, r1); // r1 = key.
|
|
|
| Handle<Code> ic = is_classic_mode()
|
| ? isolate()->builtins()->KeyedStoreIC_Initialize()
|
| @@ -2674,27 +2679,25 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
|
|
|
|
|
| void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
|
| - // Push copy of the first argument or undefined if it doesn't exist.
|
| + // r4: copy of the first argument or undefined if it doesn't exist.
|
| if (arg_count > 0) {
|
| - __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
|
| + __ ldr(r4, MemOperand(sp, arg_count * kPointerSize));
|
| } else {
|
| - __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
|
| + __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
|
| }
|
| - __ push(r1);
|
|
|
| - // Push the receiver of the enclosing function.
|
| + // r3: the receiver of the enclosing function.
|
| int receiver_offset = 2 + info_->scope()->num_parameters();
|
| - __ ldr(r1, MemOperand(fp, receiver_offset * kPointerSize));
|
| - __ push(r1);
|
| - // Push the language mode.
|
| - __ mov(r1, Operand(Smi::FromInt(language_mode())));
|
| - __ push(r1);
|
| + __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize));
|
| +
|
| + // r2: the language mode.
|
| + __ mov(r2, Operand(Smi::FromInt(language_mode())));
|
|
|
| - // Push the start position of the scope the calls resides in.
|
| + // r1: the start position of the scope the calls resides in.
|
| __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
|
| - __ push(r1);
|
|
|
| // Do the runtime call.
|
| + __ Push(r4, r3, r2, r1);
|
| __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
|
| }
|
|
|
| @@ -2768,9 +2771,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
| __ bind(&slow);
|
| // Call the runtime to find the function to call (returned in r0)
|
| // and the object holding it (returned in edx).
|
| - __ push(context_register());
|
| + ASSERT(!context_register().is(r2));
|
| __ mov(r2, Operand(proxy->name()));
|
| - __ push(r2);
|
| + __ Push(context_register(), r2);
|
| __ CallRuntime(Runtime::kLoadContextSlot, 2);
|
| __ Push(r0, r1); // Function, receiver.
|
|
|
| @@ -3487,8 +3490,7 @@ void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
|
|
|
| VisitForStackValue(args->at(1)); // index
|
| VisitForStackValue(args->at(2)); // value
|
| - __ pop(value);
|
| - __ pop(index);
|
| + __ Pop(index, value);
|
| VisitForAccumulatorValue(args->at(0)); // string
|
|
|
| if (FLAG_debug_code) {
|
| @@ -3515,8 +3517,7 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
|
|
|
| VisitForStackValue(args->at(1)); // index
|
| VisitForStackValue(args->at(2)); // value
|
| - __ pop(value);
|
| - __ pop(index);
|
| + __ Pop(index, value);
|
| VisitForAccumulatorValue(args->at(0)); // string
|
|
|
| if (FLAG_debug_code) {
|
| @@ -4260,9 +4261,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
| } else {
|
| // Non-global variable. Call the runtime to try to delete from the
|
| // context where the variable was introduced.
|
| - __ push(context_register());
|
| + ASSERT(!context_register().is(r2));
|
| __ mov(r2, Operand(var->name()));
|
| - __ push(r2);
|
| + __ Push(context_register(), r2);
|
| __ CallRuntime(Runtime::kDeleteContextSlot, 2);
|
| context()->Plug(r0);
|
| }
|
| @@ -4492,8 +4493,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
| break;
|
| }
|
| case KEYED_PROPERTY: {
|
| - __ pop(r1); // Key.
|
| - __ pop(r2); // Receiver.
|
| + __ Pop(r2, r1); // r1 = key. r2 = receiver.
|
| Handle<Code> ic = is_classic_mode()
|
| ? isolate()->builtins()->KeyedStoreIC_Initialize()
|
| : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
|
|
|