| Index: src/arm/full-codegen-arm.cc
|
| diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
|
| index 55088033f0493c9536642b2db2be22f4ff0be39f..b362f12948f9624a474a2eaa3a8154e093f72c4b 100644
|
| --- a/src/arm/full-codegen-arm.cc
|
| +++ b/src/arm/full-codegen-arm.cc
|
| @@ -119,6 +119,7 @@ class JumpPatchSite BASE_EMBEDDED {
|
| // The live registers are:
|
| // o r1: the JS function object being called (i.e., ourselves)
|
| // o cp: our context
|
| +// o pp: our caller's constant pool pointer (if FLAG_enable_ool_constant_pool)
|
| // o fp: our caller's frame pointer
|
| // o sp: stack pointer
|
| // o lr: return address
|
| @@ -162,6 +163,7 @@ void FullCodeGenerator::Generate() {
|
| info->set_prologue_offset(masm_->pc_offset());
|
| __ Prologue(BUILD_FUNCTION_FRAME);
|
| info->AddNoFrameRange(0, masm_->pc_offset());
|
| + __ LoadConstantPoolPointerRegister();
|
|
|
| { Comment cmnt(masm_, "[ Allocate locals");
|
| int locals_count = info->scope()->num_stack_slots();
|
| @@ -334,10 +336,6 @@ void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
|
|
|
| void FullCodeGenerator::EmitProfilingCounterReset() {
|
| int reset_value = FLAG_interrupt_budget;
|
| - if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
|
| - // Self-optimization is a one-off thing: if it fails, don't try again.
|
| - reset_value = Smi::kMaxValue;
|
| - }
|
| if (isolate()->IsDebuggerActive()) {
|
| // Detect debug break requests as soon as possible.
|
| reset_value = FLAG_interrupt_budget >> 4;
|
| @@ -355,13 +353,10 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
|
| Assembler::BlockConstPoolScope block_const_pool(masm_);
|
| Label ok;
|
|
|
| - int weight = 1;
|
| - if (FLAG_weighted_back_edges) {
|
| - ASSERT(back_edge_target->is_bound());
|
| - int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
|
| - weight = Min(kMaxBackEdgeWeight,
|
| - Max(1, distance / kCodeSizeMultiplier));
|
| - }
|
| + ASSERT(back_edge_target->is_bound());
|
| + int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
|
| + int weight = Min(kMaxBackEdgeWeight,
|
| + Max(1, distance / kCodeSizeMultiplier));
|
| EmitProfilingCounterDecrement(weight);
|
| __ b(pl, &ok);
|
| __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
|
| @@ -394,53 +389,41 @@ void FullCodeGenerator::EmitReturnSequence() {
|
| __ push(r0);
|
| __ CallRuntime(Runtime::kTraceExit, 1);
|
| }
|
| - if (FLAG_interrupt_at_exit || FLAG_self_optimization) {
|
| - // Pretend that the exit is a backwards jump to the entry.
|
| - int weight = 1;
|
| - if (info_->ShouldSelfOptimize()) {
|
| - weight = FLAG_interrupt_budget / FLAG_self_opt_count;
|
| - } else if (FLAG_weighted_back_edges) {
|
| - int distance = masm_->pc_offset();
|
| - weight = Min(kMaxBackEdgeWeight,
|
| - Max(1, distance / kCodeSizeMultiplier));
|
| - }
|
| - EmitProfilingCounterDecrement(weight);
|
| - Label ok;
|
| - __ b(pl, &ok);
|
| - __ push(r0);
|
| - if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
|
| - __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
| - __ push(r2);
|
| - __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
|
| - } else {
|
| - __ Call(isolate()->builtins()->InterruptCheck(),
|
| - RelocInfo::CODE_TARGET);
|
| - }
|
| - __ pop(r0);
|
| - EmitProfilingCounterReset();
|
| - __ bind(&ok);
|
| + // Pretend that the exit is a backwards jump to the entry.
|
| + int weight = 1;
|
| + if (info_->ShouldSelfOptimize()) {
|
| + weight = FLAG_interrupt_budget / FLAG_self_opt_count;
|
| + } else {
|
| + int distance = masm_->pc_offset();
|
| + weight = Min(kMaxBackEdgeWeight,
|
| + Max(1, distance / kCodeSizeMultiplier));
|
| }
|
| + EmitProfilingCounterDecrement(weight);
|
| + Label ok;
|
| + __ b(pl, &ok);
|
| + __ push(r0);
|
| + __ Call(isolate()->builtins()->InterruptCheck(),
|
| + RelocInfo::CODE_TARGET);
|
| + __ pop(r0);
|
| + EmitProfilingCounterReset();
|
| + __ bind(&ok);
|
|
|
| #ifdef DEBUG
|
| // Add a label for checking the size of the code used for returning.
|
| Label check_exit_codesize;
|
| - masm_->bind(&check_exit_codesize);
|
| + __ bind(&check_exit_codesize);
|
| #endif
|
| // Make sure that the constant pool is not emitted inside of the return
|
| // sequence.
|
| { Assembler::BlockConstPoolScope block_const_pool(masm_);
|
| - // Here we use masm_-> instead of the __ macro to avoid the code coverage
|
| - // tool from instrumenting as we rely on the code size here.
|
| int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
|
| CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
|
| // TODO(svenpanne) The code below is sometimes 4 words, sometimes 5!
|
| PredictableCodeSizeScope predictable(masm_, -1);
|
| __ RecordJSReturn();
|
| - masm_->mov(sp, fp);
|
| - int no_frame_start = masm_->pc_offset();
|
| - masm_->ldm(ia_w, sp, fp.bit() | lr.bit());
|
| - masm_->add(sp, sp, Operand(sp_delta));
|
| - masm_->Jump(lr);
|
| + int no_frame_start = __ LeaveFrame(StackFrame::JAVA_SCRIPT);
|
| + __ add(sp, sp, Operand(sp_delta));
|
| + __ Jump(lr);
|
| info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
|
| }
|
|
|
| @@ -1040,6 +1023,16 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
| CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
|
| patch_site.EmitPatchInfo();
|
|
|
| + Label skip;
|
| + __ b(&skip);
|
| + PrepareForBailout(clause, TOS_REG);
|
| + __ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
| + __ cmp(r0, ip);
|
| + __ b(ne, &next_test);
|
| + __ Drop(1);
|
| + __ jmp(clause->body_target());
|
| + __ bind(&skip);
|
| +
|
| __ cmp(r0, Operand::Zero());
|
| __ b(ne, &next_test);
|
| __ Drop(1); // Switch value is no longer needed.
|
| @@ -2169,11 +2162,12 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
|
| __ bind(&resume_frame);
|
| // lr = return address.
|
| // fp = caller's frame pointer.
|
| + // pp = caller's constant pool (if FLAG_enable_ool_constant_pool),
|
| // cp = callee's context,
|
| // r4 = callee's JS function.
|
| - __ Push(lr, fp, cp, r4);
|
| + __ PushFixedFrame(r4);
|
| // Adjust FP to point to saved FP.
|
| - __ add(fp, sp, Operand(2 * kPointerSize));
|
| + __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
|
|
|
| // Load the operand stack size.
|
| __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
|
| @@ -2454,12 +2448,9 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
| // Const initializers need a write barrier.
|
| ASSERT(!var->IsParameter()); // No const parameters.
|
| if (var->IsStackLocal()) {
|
| - Label skip;
|
| __ ldr(r1, StackOperand(var));
|
| __ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
|
| - __ b(ne, &skip);
|
| - __ str(result_register(), StackOperand(var));
|
| - __ bind(&skip);
|
| + __ str(result_register(), StackOperand(var), eq);
|
| } else {
|
| ASSERT(var->IsContextSlot() || var->IsLookupSlot());
|
| // Like var declarations, const declarations are hoisted to function
|
| @@ -3196,14 +3187,11 @@ void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
|
| __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
|
|
| // Skip the arguments adaptor frame if it exists.
|
| - Label check_frame_marker;
|
| __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
|
| __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
| - __ b(ne, &check_frame_marker);
|
| - __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
|
| + __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset), eq);
|
|
|
| // Check the marker in the calling frame.
|
| - __ bind(&check_frame_marker);
|
| __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
|
| __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
|
| PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
| @@ -3254,7 +3242,7 @@ void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
|
|
|
| void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
|
| ASSERT(expr->arguments()->length() == 0);
|
| - Label exit;
|
| +
|
| // Get the number of formal parameters.
|
| __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
|
|
|
| @@ -3262,13 +3250,11 @@ void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
|
| __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
| __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
|
| __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
| - __ b(ne, &exit);
|
|
|
| // Arguments adaptor case: Read the arguments length from the
|
| // adaptor frame.
|
| - __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
| + __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset), eq);
|
|
|
| - __ bind(&exit);
|
| context()->Plug(r0);
|
| }
|
|
|
| @@ -3393,8 +3379,7 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
|
| __ JumpIfSmi(r0, &done);
|
| // If the object is not a value type, return the object.
|
| __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
|
| - __ b(ne, &done);
|
| - __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
|
| + __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset), eq);
|
|
|
| __ bind(&done);
|
| context()->Plug(r0);
|
| @@ -3713,13 +3698,11 @@ void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
|
|
|
|
|
| void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
|
| - // Load the argument on the stack and call the stub.
|
| - TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
| - TranscendentalCacheStub::TAGGED);
|
| + // Load the argument on the stack and call the runtime function.
|
| ZoneList<Expression*>* args = expr->arguments();
|
| ASSERT(args->length() == 1);
|
| VisitForStackValue(args->at(0));
|
| - __ CallStub(&stub);
|
| + __ CallRuntime(Runtime::kMath_log, 1);
|
| context()->Plug(r0);
|
| }
|
|
|
|
|