| Index: src/arm/lithium-codegen-arm.cc
|
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
|
| index 0aa8197ce1fe128098ef6f5c742592eb976f5653..164ee553daa0fd409d8e786882c1bb576a254fb2 100644
|
| --- a/src/arm/lithium-codegen-arm.cc
|
| +++ b/src/arm/lithium-codegen-arm.cc
|
| @@ -98,6 +98,38 @@ void LCodeGen::Abort(BailoutReason reason) {
|
| }
|
|
|
|
|
| +void LCodeGen::SaveCallerDoubles() {
|
| + ASSERT(info()->saves_caller_doubles());
|
| + ASSERT(NeedsEagerFrame());
|
| + Comment(";;; Save clobbered callee double registers");
|
| + int count = 0;
|
| + BitVector* doubles = chunk()->allocated_double_registers();
|
| + BitVector::Iterator save_iterator(doubles);
|
| + while (!save_iterator.Done()) {
|
| + __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()),
|
| + MemOperand(sp, count * kDoubleSize));
|
| + save_iterator.Advance();
|
| + count++;
|
| + }
|
| +}
|
| +
|
| +
|
| +void LCodeGen::RestoreCallerDoubles() {
|
| + ASSERT(info()->saves_caller_doubles());
|
| + ASSERT(NeedsEagerFrame());
|
| + Comment(";;; Restore clobbered callee double registers");
|
| + BitVector* doubles = chunk()->allocated_double_registers();
|
| + BitVector::Iterator save_iterator(doubles);
|
| + int count = 0;
|
| + while (!save_iterator.Done()) {
|
| + __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()),
|
| + MemOperand(sp, count * kDoubleSize));
|
| + save_iterator.Advance();
|
| + count++;
|
| + }
|
| +}
|
| +
|
| +
|
| bool LCodeGen::GeneratePrologue() {
|
| ASSERT(is_generating());
|
|
|
| @@ -158,16 +190,7 @@ bool LCodeGen::GeneratePrologue() {
|
| }
|
|
|
| if (info()->saves_caller_doubles()) {
|
| - Comment(";;; Save clobbered callee double registers");
|
| - int count = 0;
|
| - BitVector* doubles = chunk()->allocated_double_registers();
|
| - BitVector::Iterator save_iterator(doubles);
|
| - while (!save_iterator.Done()) {
|
| - __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()),
|
| - MemOperand(sp, count * kDoubleSize));
|
| - save_iterator.Advance();
|
| - count++;
|
| - }
|
| + SaveCallerDoubles();
|
| }
|
|
|
| // Possibly allocate a local context.
|
| @@ -313,6 +336,7 @@ bool LCodeGen::GenerateDeoptJumpTable() {
|
| Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id);
|
| }
|
| if (deopt_jump_table_[i].needs_frame) {
|
| + ASSERT(!info()->saves_caller_doubles());
|
| __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry)));
|
| if (needs_frame.is_bound()) {
|
| __ b(&needs_frame);
|
| @@ -330,6 +354,10 @@ bool LCodeGen::GenerateDeoptJumpTable() {
|
| __ mov(pc, ip);
|
| }
|
| } else {
|
| + if (info()->saves_caller_doubles()) {
|
| + ASSERT(info()->IsStub());
|
| + RestoreCallerDoubles();
|
| + }
|
| __ mov(lr, Operand(pc), LeaveCC, al);
|
| __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry)));
|
| }
|
| @@ -828,7 +856,10 @@ void LCodeGen::DeoptimizeIf(Condition condition,
|
| }
|
|
|
| ASSERT(info()->IsStub() || frame_is_built_);
|
| - if (condition == al && frame_is_built_) {
|
| + // Go through jump table if we need to handle condition, build frame, or
|
| + // restore caller doubles.
|
| + if (condition == al && frame_is_built_ &&
|
| + !info()->saves_caller_doubles()) {
|
| __ Call(entry, RelocInfo::RUNTIME_ENTRY);
|
| } else {
|
| // We often have several deopts to the same entry, reuse the last
|
| @@ -2929,16 +2960,7 @@ void LCodeGen::DoReturn(LReturn* instr) {
|
| __ CallRuntime(Runtime::kTraceExit, 1);
|
| }
|
| if (info()->saves_caller_doubles()) {
|
| - ASSERT(NeedsEagerFrame());
|
| - BitVector* doubles = chunk()->allocated_double_registers();
|
| - BitVector::Iterator save_iterator(doubles);
|
| - int count = 0;
|
| - while (!save_iterator.Done()) {
|
| - __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()),
|
| - MemOperand(sp, count * kDoubleSize));
|
| - save_iterator.Advance();
|
| - count++;
|
| - }
|
| + RestoreCallerDoubles();
|
| }
|
| int no_frame_start = -1;
|
| if (NeedsEagerFrame()) {
|
| @@ -3934,68 +3956,6 @@ void LCodeGen::DoPower(LPower* instr) {
|
| }
|
|
|
|
|
| -void LCodeGen::DoRandom(LRandom* instr) {
|
| - // Assert that the register size is indeed the size of each seed.
|
| - static const int kSeedSize = sizeof(uint32_t);
|
| - STATIC_ASSERT(kPointerSize == kSeedSize);
|
| -
|
| - // Load native context
|
| - Register global_object = ToRegister(instr->global_object());
|
| - Register native_context = global_object;
|
| - __ ldr(native_context, FieldMemOperand(
|
| - global_object, GlobalObject::kNativeContextOffset));
|
| -
|
| - // Load state (FixedArray of the native context's random seeds)
|
| - static const int kRandomSeedOffset =
|
| - FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
|
| - Register state = native_context;
|
| - __ ldr(state, FieldMemOperand(native_context, kRandomSeedOffset));
|
| -
|
| - // Load state[0].
|
| - Register state0 = ToRegister(instr->scratch());
|
| - __ ldr(state0, FieldMemOperand(state, ByteArray::kHeaderSize));
|
| - // Load state[1].
|
| - Register state1 = ToRegister(instr->scratch2());
|
| - __ ldr(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize));
|
| -
|
| - // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
|
| - Register scratch3 = ToRegister(instr->scratch3());
|
| - Register scratch4 = scratch0();
|
| - __ and_(scratch3, state0, Operand(0xFFFF));
|
| - __ mov(scratch4, Operand(18273));
|
| - __ mul(scratch3, scratch3, scratch4);
|
| - __ add(state0, scratch3, Operand(state0, LSR, 16));
|
| - // Save state[0].
|
| - __ str(state0, FieldMemOperand(state, ByteArray::kHeaderSize));
|
| -
|
| - // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
|
| - __ and_(scratch3, state1, Operand(0xFFFF));
|
| - __ mov(scratch4, Operand(36969));
|
| - __ mul(scratch3, scratch3, scratch4);
|
| - __ add(state1, scratch3, Operand(state1, LSR, 16));
|
| - // Save state[1].
|
| - __ str(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize));
|
| -
|
| - // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
|
| - Register random = scratch4;
|
| - __ and_(random, state1, Operand(0x3FFFF));
|
| - __ add(random, random, Operand(state0, LSL, 14));
|
| -
|
| - // 0x41300000 is the top half of 1.0 x 2^20 as a double.
|
| - // Create this constant using mov/orr to avoid PC relative load.
|
| - __ mov(scratch3, Operand(0x41000000));
|
| - __ orr(scratch3, scratch3, Operand(0x300000));
|
| - // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
|
| - DwVfpRegister result = ToDoubleRegister(instr->result());
|
| - __ vmov(result, random, scratch3);
|
| - // Move 0x4130000000000000 to VFP.
|
| - __ mov(scratch4, Operand::Zero());
|
| - DwVfpRegister scratch5 = double_scratch0();
|
| - __ vmov(scratch5, scratch4, scratch3);
|
| - __ vsub(result, result, scratch5);
|
| -}
|
| -
|
| -
|
| void LCodeGen::DoMathExp(LMathExp* instr) {
|
| DwVfpRegister input = ToDoubleRegister(instr->value());
|
| DwVfpRegister result = ToDoubleRegister(instr->result());
|
| @@ -4735,10 +4695,13 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
|
| void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) {
|
| LOperand* input = instr->value();
|
| LOperand* output = instr->result();
|
| - __ SmiTag(ToRegister(output), ToRegister(input), SetCC);
|
| + ASSERT(output->IsRegister());
|
| if (!instr->hydrogen()->value()->HasRange() ||
|
| !instr->hydrogen()->value()->range()->IsInSmiRange()) {
|
| + __ SmiTag(ToRegister(output), ToRegister(input), SetCC);
|
| DeoptimizeIf(vs, instr->environment());
|
| + } else {
|
| + __ SmiTag(ToRegister(output), ToRegister(input));
|
| }
|
| }
|
|
|
| @@ -5597,22 +5560,21 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
| Register scratch = scratch0();
|
| if (type_name->Equals(heap()->number_string())) {
|
| __ JumpIfSmi(input, true_label);
|
| - __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
|
| - __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
| - __ cmp(input, Operand(ip));
|
| + __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
|
| + __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
|
| final_branch_condition = eq;
|
|
|
| } else if (type_name->Equals(heap()->string_string())) {
|
| __ JumpIfSmi(input, false_label);
|
| - __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
|
| + __ CompareObjectType(input, scratch, no_reg, FIRST_NONSTRING_TYPE);
|
| __ b(ge, false_label);
|
| - __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
| - __ tst(ip, Operand(1 << Map::kIsUndetectable));
|
| + __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
| + __ tst(scratch, Operand(1 << Map::kIsUndetectable));
|
| final_branch_condition = eq;
|
|
|
| } else if (type_name->Equals(heap()->symbol_string())) {
|
| __ JumpIfSmi(input, false_label);
|
| - __ CompareObjectType(input, input, scratch, SYMBOL_TYPE);
|
| + __ CompareObjectType(input, scratch, no_reg, SYMBOL_TYPE);
|
| final_branch_condition = eq;
|
|
|
| } else if (type_name->Equals(heap()->boolean_string())) {
|
| @@ -5630,33 +5592,35 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
| __ b(eq, true_label);
|
| __ JumpIfSmi(input, false_label);
|
| // Check for undetectable objects => true.
|
| - __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
|
| - __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
| - __ tst(ip, Operand(1 << Map::kIsUndetectable));
|
| + __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
|
| + __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
| + __ tst(scratch, Operand(1 << Map::kIsUndetectable));
|
| final_branch_condition = ne;
|
|
|
| } else if (type_name->Equals(heap()->function_string())) {
|
| STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
| + Register type_reg = scratch;
|
| __ JumpIfSmi(input, false_label);
|
| - __ CompareObjectType(input, scratch, input, JS_FUNCTION_TYPE);
|
| + __ CompareObjectType(input, scratch, type_reg, JS_FUNCTION_TYPE);
|
| __ b(eq, true_label);
|
| - __ cmp(input, Operand(JS_FUNCTION_PROXY_TYPE));
|
| + __ cmp(type_reg, Operand(JS_FUNCTION_PROXY_TYPE));
|
| final_branch_condition = eq;
|
|
|
| } else if (type_name->Equals(heap()->object_string())) {
|
| + Register map = scratch;
|
| __ JumpIfSmi(input, false_label);
|
| if (!FLAG_harmony_typeof) {
|
| __ CompareRoot(input, Heap::kNullValueRootIndex);
|
| __ b(eq, true_label);
|
| }
|
| - __ CompareObjectType(input, input, scratch,
|
| - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
| - __ b(lt, false_label);
|
| - __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
| - __ b(gt, false_label);
|
| + __ CheckObjectTypeRange(input,
|
| + map,
|
| + FIRST_NONCALLABLE_SPEC_OBJECT_TYPE,
|
| + LAST_NONCALLABLE_SPEC_OBJECT_TYPE,
|
| + false_label);
|
| // Check for undetectable objects => false.
|
| - __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
| - __ tst(ip, Operand(1 << Map::kIsUndetectable));
|
| + __ ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
|
| + __ tst(scratch, Operand(1 << Map::kIsUndetectable));
|
| final_branch_condition = eq;
|
|
|
| } else {
|
|
|