diff options
Diffstat (limited to 'deps/v8/src/arm/stub-cache-arm.cc')
-rw-r--r-- | deps/v8/src/arm/stub-cache-arm.cc | 139 |
1 files changed, 98 insertions, 41 deletions
diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc index 06f8385af9..49c0982301 100644 --- a/deps/v8/src/arm/stub-cache-arm.cc +++ b/deps/v8/src/arm/stub-cache-arm.cc @@ -443,8 +443,10 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, Label exit; // Check that the map of the object hasn't changed. + CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS + : REQUIRE_EXACT_MAP; __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label, - DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); + DO_SMI_CHECK, mode); // Perform global security token check if needed. if (object->IsJSGlobalProxy()) { @@ -580,6 +582,8 @@ static void PushInterceptorArguments(MacroAssembler* masm, __ push(holder); __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); __ push(scratch); + __ mov(scratch, Operand(ExternalReference::isolate_address())); + __ push(scratch); } @@ -594,7 +598,7 @@ static void CompileCallLoadPropertyWithInterceptor( ExternalReference ref = ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), masm->isolate()); - __ mov(r0, Operand(5)); + __ mov(r0, Operand(6)); __ mov(r1, Operand(ref)); CEntryStub stub(1); @@ -602,9 +606,9 @@ static void CompileCallLoadPropertyWithInterceptor( } -static const int kFastApiCallArguments = 3; +static const int kFastApiCallArguments = 4; -// Reserves space for the extra arguments to FastHandleApiCall in the +// Reserves space for the extra arguments to API function in the // caller's frame. // // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. @@ -630,7 +634,8 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm, // -- sp[0] : holder (set by CheckPrototypes) // -- sp[4] : callee JS function // -- sp[8] : call data - // -- sp[12] : last JS argument + // -- sp[12] : isolate + // -- sp[16] : last JS argument // -- ... // -- sp[(argc + 3) * 4] : first JS argument // -- sp[(argc + 4) * 4] : receiver @@ -640,7 +645,7 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm, __ LoadHeapObject(r5, function); __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); - // Pass the additional arguments FastHandleApiCall expects. + // Pass the additional arguments. Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); Handle<Object> call_data(api_call_info->data()); if (masm->isolate()->heap()->InNewSpace(*call_data)) { @@ -649,13 +654,15 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm, } else { __ Move(r6, call_data); } - // Store JS function and call data. - __ stm(ib, sp, r5.bit() | r6.bit()); + __ mov(r7, Operand(ExternalReference::isolate_address())); + // Store JS function, call data and isolate. + __ stm(ib, sp, r5.bit() | r6.bit() | r7.bit()); - // r2 points to call data as expected by Arguments - // (refer to layout above). - __ add(r2, sp, Operand(2 * kPointerSize)); + // Prepare arguments. + __ add(r2, sp, Operand(3 * kPointerSize)); + // Allocate the v8::Arguments structure in the arguments' space since + // it's not controlled by GC. const int kApiStackSpace = 4; FrameScope frame_scope(masm, StackFrame::MANUAL); @@ -664,9 +671,9 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm, // r0 = v8::Arguments& // Arguments is after the return address. __ add(r0, sp, Operand(1 * kPointerSize)); - // v8::Arguments::implicit_args = data + // v8::Arguments::implicit_args_ __ str(r2, MemOperand(r0, 0 * kPointerSize)); - // v8::Arguments::values = last argument + // v8::Arguments::values_ __ add(ip, r2, Operand(argc * kPointerSize)); __ str(ip, MemOperand(r0, 1 * kPointerSize)); // v8::Arguments::length_ = argc @@ -843,7 +850,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { __ CallExternalReference( ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), masm->isolate()), - 5); + 6); // Restore the name_ register. __ pop(name_); // Leave the internal frame. @@ -1202,7 +1209,9 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, } else { __ Move(scratch3, Handle<Object>(callback->data())); } - __ Push(reg, scratch3, name_reg); + __ Push(reg, scratch3); + __ mov(scratch3, Operand(ExternalReference::isolate_address())); + __ Push(scratch3, name_reg); __ mov(r0, sp); // r0 = Handle<String> const int kApiStackSpace = 1; @@ -1214,7 +1223,7 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& - const int kStackUnwindSpace = 4; + const int kStackUnwindSpace = 5; Address getter_address = v8::ToCData<Address>(callback->getter()); ApiFunction fun(getter_address); ExternalReference ref = @@ -1264,12 +1273,19 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, name, miss); ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); + // Preserve the receiver register explicitly whenever it is different from + // the holder and it is needed should the interceptor return without any + // result. The CALLBACKS case needs the receiver to be passed into C++ code, + // the FIELD case might cause a miss during the prototype check. + bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); + bool must_preserve_receiver_reg = !receiver.is(holder_reg) && + (lookup->type() == CALLBACKS || must_perfrom_prototype_check); + // Save necessary data before invoking an interceptor. // Requires a frame to make GC aware of pushed pointers. { FrameScope frame_scope(masm(), StackFrame::INTERNAL); - if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { - // CALLBACKS case needs a receiver to be passed into C++ callback. + if (must_preserve_receiver_reg) { __ Push(receiver, holder_reg, name_reg); } else { __ Push(holder_reg, name_reg); @@ -1294,14 +1310,14 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, __ bind(&interceptor_failed); __ pop(name_reg); __ pop(holder_reg); - if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { + if (must_preserve_receiver_reg) { __ pop(receiver); } // Leave the internal frame. } // Check that the maps from interceptor's holder to lookup's holder // haven't changed. And load lookup's holder into |holder| register. - if (*interceptor_holder != lookup->holder()) { + if (must_perfrom_prototype_check) { holder_reg = CheckPrototypes(interceptor_holder, holder_reg, Handle<JSObject>(lookup->holder()), @@ -1335,20 +1351,19 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, if (!receiver.is(holder_reg)) { ASSERT(scratch1.is(holder_reg)); __ Push(receiver, holder_reg); - __ ldr(scratch3, - FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); - __ Push(scratch3, scratch2, name_reg); } else { __ push(receiver); - __ ldr(scratch3, - FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); - __ Push(holder_reg, scratch3, scratch2, name_reg); + __ push(holder_reg); } + __ ldr(scratch3, + FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); + __ mov(scratch1, Operand(ExternalReference::isolate_address())); + __ Push(scratch3, scratch1, scratch2, name_reg); ExternalReference ref = ExternalReference(IC_Utility(IC::kLoadCallbackProperty), masm()->isolate()); - __ TailCallExternalReference(ref, 5, 1); + __ TailCallExternalReference(ref, 6, 1); } } else { // !compile_followup_inline // Call the runtime system to load the interceptor. @@ -1362,7 +1377,7 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, ExternalReference ref = ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), masm()->isolate()); - __ TailCallExternalReference(ref, 5, 1); + __ TailCallExternalReference(ref, 6, 1); } } @@ -1730,7 +1745,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall( // We can't address the last element in one operation. Compute the more // expensive shift first, and use an offset later on. __ add(elements, elements, Operand(r4, LSL, kPointerSizeLog2 - kSmiTagSize)); - __ ldr(r0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); + __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize)); __ cmp(r0, r6); __ b(eq, &call_builtin); @@ -1738,7 +1753,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall( __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); // Fill with the hole. - __ str(r6, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); + __ str(r6, FieldMemOperand(elements, FixedArray::kHeaderSize)); __ Drop(argc + 1); __ Ret(); @@ -3368,6 +3383,44 @@ static bool IsElementTypeSigned(ElementsKind elements_kind) { } +static void GenerateSmiKeyCheck(MacroAssembler* masm, + Register key, + Register scratch0, + Register scratch1, + DwVfpRegister double_scratch0, + Label* fail) { + if (CpuFeatures::IsSupported(VFP3)) { + CpuFeatures::Scope scope(VFP3); + Label key_ok; + // Check for smi or a smi inside a heap number. We convert the heap + // number and check if the conversion is exact and fits into the smi + // range. + __ JumpIfSmi(key, &key_ok); + __ CheckMap(key, + scratch0, + Heap::kHeapNumberMapRootIndex, + fail, + DONT_DO_SMI_CHECK); + __ sub(ip, key, Operand(kHeapObjectTag)); + __ vldr(double_scratch0, ip, HeapNumber::kValueOffset); + __ EmitVFPTruncate(kRoundToZero, + double_scratch0.low(), + double_scratch0, + scratch0, + scratch1, + kCheckForInexactConversion); + __ b(ne, fail); + __ vmov(scratch0, double_scratch0.low()); + __ TrySmiTag(scratch0, fail, scratch1); + __ mov(key, scratch0); + __ bind(&key_ok); + } else { + // Check that the key is a smi. + __ JumpIfNotSmi(key, fail); + } +} + + void KeyedLoadStubCompiler::GenerateLoadExternalArray( MacroAssembler* masm, ElementsKind elements_kind) { @@ -3384,8 +3437,8 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(key, &miss_force_generic); + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key, r4, r5, d1, &miss_force_generic); __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); // r3: elements array @@ -3715,8 +3768,8 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(key, &miss_force_generic); + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key, r4, r5, d1, &miss_force_generic); __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); @@ -4041,8 +4094,8 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(r0, &miss_force_generic); + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, r0, r4, r5, d1, &miss_force_generic); // Get the elements array. __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset)); @@ -4093,8 +4146,8 @@ void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(key_reg, &miss_force_generic); + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, &miss_force_generic); // Get the elements array. __ ldr(elements_reg, @@ -4169,8 +4222,8 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement( // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(key_reg, &miss_force_generic); + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, &miss_force_generic); if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { __ JumpIfNotSmi(value_reg, &transition_elements_kind); @@ -4336,7 +4389,9 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - __ JumpIfNotSmi(key_reg, &miss_force_generic); + + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, &miss_force_generic); __ ldr(elements_reg, FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); @@ -4427,6 +4482,8 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( // Increment the length of the array. __ mov(length_reg, Operand(Smi::FromInt(1))); __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); + __ ldr(elements_reg, + FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); __ jmp(&finish_store); __ bind(&check_capacity); |