| Index: src/arm/lithium-codegen-arm.cc
|
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
|
| index 4b05db1d6a0e4138446501a636d67ccc392721c5..8f1c9c090dfbdf6e1de38ed34c1f028a2efbe8b0 100644
|
| --- a/src/arm/lithium-codegen-arm.cc
|
| +++ b/src/arm/lithium-codegen-arm.cc
|
| @@ -84,9 +84,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
|
| ASSERT(is_done());
|
| code->set_stack_slots(GetStackSlotCount());
|
| code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
|
| - if (FLAG_weak_embedded_maps_in_optimized_code) {
|
| - RegisterDependentCodeForEmbeddedMaps(code);
|
| - }
|
| + RegisterDependentCodeForEmbeddedMaps(code);
|
| PopulateDeoptimizationData(code);
|
| info()->CommitDependencies(code);
|
| }
|
| @@ -887,36 +885,6 @@ void LCodeGen::DeoptimizeIf(Condition condition,
|
| }
|
|
|
|
|
| -void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
|
| - ZoneList<Handle<Map> > maps(1, zone());
|
| - ZoneList<Handle<JSObject> > objects(1, zone());
|
| - int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
|
| - for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
|
| - if (Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) {
|
| - if (it.rinfo()->target_object()->IsMap()) {
|
| - Handle<Map> map(Map::cast(it.rinfo()->target_object()));
|
| - maps.Add(map, zone());
|
| - } else if (it.rinfo()->target_object()->IsJSObject()) {
|
| - Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object()));
|
| - objects.Add(object, zone());
|
| - }
|
| - }
|
| - }
|
| -#ifdef VERIFY_HEAP
|
| - // This disables verification of weak embedded objects after full GC.
|
| - // AddDependentCode can cause a GC, which would observe the state where
|
| - // this code is not yet in the depended code lists of the embedded maps.
|
| - NoWeakObjectVerificationScope disable_verification_of_embedded_objects;
|
| -#endif
|
| - for (int i = 0; i < maps.length(); i++) {
|
| - maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code);
|
| - }
|
| - for (int i = 0; i < objects.length(); i++) {
|
| - AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code);
|
| - }
|
| -}
|
| -
|
| -
|
| void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
|
| int length = deoptimizations_.length();
|
| if (length == 0) return;
|
| @@ -2047,8 +2015,7 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
|
|
|
|
|
| void LCodeGen::DoThrow(LThrow* instr) {
|
| - Register input_reg = EmitLoadRegister(instr->value(), ip);
|
| - __ push(input_reg);
|
| + __ push(ToRegister(instr->value()));
|
| ASSERT(ToRegister(instr->context()).is(cp));
|
| CallRuntime(Runtime::kThrow, 1, instr);
|
|
|
| @@ -2164,9 +2131,6 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
|
| __ vdiv(result, left, right);
|
| break;
|
| case Token::MOD: {
|
| - // Save r0-r3 on the stack.
|
| - __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
|
| -
|
| __ PrepareCallCFunction(0, 2, scratch0());
|
| __ SetCallCDoubleArguments(left, right);
|
| __ CallCFunction(
|
| @@ -2174,9 +2138,6 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
|
| 0, 2);
|
| // Move the result in the double result register.
|
| __ GetCFunctionDoubleResult(result);
|
| -
|
| - // Restore r0-r3.
|
| - __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
|
| break;
|
| }
|
| default:
|
| @@ -2192,7 +2153,7 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
|
| ASSERT(ToRegister(instr->right()).is(r0));
|
| ASSERT(ToRegister(instr->result()).is(r0));
|
|
|
| - BinaryOpStub stub(instr->op(), NO_OVERWRITE);
|
| + BinaryOpICStub stub(instr->op(), NO_OVERWRITE);
|
| // Block literal pool emission to ensure nop indicating no inlined smi code
|
| // is in the correct position.
|
| Assembler::BlockConstPoolScope block_const_pool(masm());
|
| @@ -3502,12 +3463,13 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
|
| void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
| Register receiver = ToRegister(instr->receiver());
|
| Register function = ToRegister(instr->function());
|
| + Register result = ToRegister(instr->result());
|
| Register scratch = scratch0();
|
|
|
| // If the receiver is null or undefined, we have to pass the global
|
| // object as a receiver to normal functions. Values have to be
|
| // passed unchanged to builtins and strict-mode functions.
|
| - Label global_object, receiver_ok;
|
| + Label global_object, result_in_receiver;
|
|
|
| // Do not transform the receiver to object for strict mode
|
| // functions.
|
| @@ -3517,11 +3479,11 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
| FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
|
| __ tst(scratch,
|
| Operand(1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize)));
|
| - __ b(ne, &receiver_ok);
|
| + __ b(ne, &result_in_receiver);
|
|
|
| // Do not transform the receiver to object for builtins.
|
| __ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
|
| - __ b(ne, &receiver_ok);
|
| + __ b(ne, &result_in_receiver);
|
|
|
| // Normal function. Replace undefined or null with global receiver.
|
| __ LoadRoot(scratch, Heap::kNullValueRootIndex);
|
| @@ -3536,13 +3498,21 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
| DeoptimizeIf(eq, instr->environment());
|
| __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
|
| DeoptimizeIf(lt, instr->environment());
|
| - __ jmp(&receiver_ok);
|
| + __ b(&result_in_receiver);
|
|
|
| __ bind(&global_object);
|
| - __ ldr(receiver, GlobalObjectOperand());
|
| - __ ldr(receiver,
|
| - FieldMemOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
|
| - __ bind(&receiver_ok);
|
| + __ ldr(result, GlobalObjectOperand());
|
| + __ ldr(result,
|
| + FieldMemOperand(result, JSGlobalObject::kGlobalReceiverOffset));
|
| + if (result.is(receiver)) {
|
| + __ bind(&result_in_receiver);
|
| + } else {
|
| + Label result_ok;
|
| + __ b(&result_ok);
|
| + __ bind(&result_in_receiver);
|
| + __ mov(result, receiver);
|
| + __ bind(&result_ok);
|
| + }
|
| }
|
|
|
|
|
| @@ -3903,7 +3873,7 @@ void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
|
| void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
|
| DwVfpRegister input = ToDoubleRegister(instr->value());
|
| DwVfpRegister result = ToDoubleRegister(instr->result());
|
| - DwVfpRegister temp = ToDoubleRegister(instr->temp());
|
| + DwVfpRegister temp = double_scratch0();
|
|
|
| // Note that according to ECMA-262 15.8.2.13:
|
| // Math.pow(-Infinity, 0.5) == Infinity
|
| @@ -3926,11 +3896,11 @@ void LCodeGen::DoPower(LPower* instr) {
|
| // Having marked this as a call, we can use any registers.
|
| // Just make sure that the input/output registers are the expected ones.
|
| ASSERT(!instr->right()->IsDoubleRegister() ||
|
| - ToDoubleRegister(instr->right()).is(d2));
|
| + ToDoubleRegister(instr->right()).is(d1));
|
| ASSERT(!instr->right()->IsRegister() ||
|
| ToRegister(instr->right()).is(r2));
|
| - ASSERT(ToDoubleRegister(instr->left()).is(d1));
|
| - ASSERT(ToDoubleRegister(instr->result()).is(d3));
|
| + ASSERT(ToDoubleRegister(instr->left()).is(d0));
|
| + ASSERT(ToDoubleRegister(instr->result()).is(d2));
|
|
|
| if (exponent_type.IsSmi()) {
|
| MathPowStub stub(MathPowStub::TAGGED);
|
| @@ -3981,39 +3951,6 @@ void LCodeGen::DoMathLog(LMathLog* instr) {
|
| }
|
|
|
|
|
| -void LCodeGen::DoMathTan(LMathTan* instr) {
|
| - ASSERT(ToDoubleRegister(instr->result()).is(d2));
|
| - // Set the context register to a GC-safe fake value. Clobbering it is
|
| - // OK because this instruction is marked as a call.
|
| - __ mov(cp, Operand::Zero());
|
| - TranscendentalCacheStub stub(TranscendentalCache::TAN,
|
| - TranscendentalCacheStub::UNTAGGED);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| -}
|
| -
|
| -
|
| -void LCodeGen::DoMathCos(LMathCos* instr) {
|
| - ASSERT(ToDoubleRegister(instr->result()).is(d2));
|
| - // Set the context register to a GC-safe fake value. Clobbering it is
|
| - // OK because this instruction is marked as a call.
|
| - __ mov(cp, Operand::Zero());
|
| - TranscendentalCacheStub stub(TranscendentalCache::COS,
|
| - TranscendentalCacheStub::UNTAGGED);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| -}
|
| -
|
| -
|
| -void LCodeGen::DoMathSin(LMathSin* instr) {
|
| - ASSERT(ToDoubleRegister(instr->result()).is(d2));
|
| - // Set the context register to a GC-safe fake value. Clobbering it is
|
| - // OK because this instruction is marked as a call.
|
| - __ mov(cp, Operand::Zero());
|
| - TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
| - TranscendentalCacheStub::UNTAGGED);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| -}
|
| -
|
| -
|
| void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
|
| ASSERT(ToRegister(instr->context()).is(cp));
|
| ASSERT(ToRegister(instr->function()).is(r1));
|
| @@ -4176,7 +4113,13 @@ void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
|
| void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
|
| Register result = ToRegister(instr->result());
|
| Register base = ToRegister(instr->base_object());
|
| - __ add(result, base, Operand(instr->offset()));
|
| + if (instr->offset()->IsConstantOperand()) {
|
| + LConstantOperand* offset = LConstantOperand::cast(instr->offset());
|
| + __ add(result, base, Operand(ToInteger32(offset)));
|
| + } else {
|
| + Register offset = ToRegister(instr->offset());
|
| + __ add(result, base, offset);
|
| + }
|
| }
|
|
|
|
|
| @@ -4695,10 +4638,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));
|
| }
|
| }
|
|
|
| @@ -4765,14 +4711,13 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
|
| LNumberTagU* instr_;
|
| };
|
|
|
| - LOperand* input = instr->value();
|
| - ASSERT(input->IsRegister() && input->Equals(instr->result()));
|
| - Register reg = ToRegister(input);
|
| + Register input = ToRegister(instr->value());
|
| + Register result = ToRegister(instr->result());
|
|
|
| DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr);
|
| - __ cmp(reg, Operand(Smi::kMaxValue));
|
| + __ cmp(input, Operand(Smi::kMaxValue));
|
| __ b(hi, deferred->entry());
|
| - __ SmiTag(reg, reg);
|
| + __ SmiTag(result, input);
|
| __ bind(deferred->exit());
|
| }
|
|
|
| @@ -5557,22 +5502,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())) {
|
| @@ -5590,33 +5534,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 {
|
|
|