|
|
@ -406,7 +406,6 @@ static void PushInterceptorArguments(MacroAssembler* masm, |
|
|
|
__ push(receiver); |
|
|
|
__ push(holder); |
|
|
|
__ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); |
|
|
|
__ push(Immediate(reinterpret_cast<int>(masm->isolate()))); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -420,12 +419,12 @@ static void CompileCallLoadPropertyWithInterceptor( |
|
|
|
__ CallExternalReference( |
|
|
|
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
|
|
|
masm->isolate()), |
|
|
|
6); |
|
|
|
5); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Number of pointers to be reserved on stack for fast API call.
|
|
|
|
static const int kFastApiCallArguments = 4; |
|
|
|
static const int kFastApiCallArguments = 3; |
|
|
|
|
|
|
|
|
|
|
|
// Reserves space for the extra arguments to API function in the
|
|
|
@ -473,11 +472,10 @@ static void GenerateFastApiCall(MacroAssembler* masm, |
|
|
|
// -- esp[8] : api function
|
|
|
|
// (first fast api call extra argument)
|
|
|
|
// -- esp[12] : api call data
|
|
|
|
// -- esp[16] : isolate
|
|
|
|
// -- esp[20] : last argument
|
|
|
|
// -- esp[16] : last argument
|
|
|
|
// -- ...
|
|
|
|
// -- esp[(argc + 4) * 4] : first argument
|
|
|
|
// -- esp[(argc + 5) * 4] : receiver
|
|
|
|
// -- esp[(argc + 3) * 4] : first argument
|
|
|
|
// -- esp[(argc + 4) * 4] : receiver
|
|
|
|
// -----------------------------------
|
|
|
|
// Get the function and setup the context.
|
|
|
|
Handle<JSFunction> function = optimization.constant_function(); |
|
|
@ -495,11 +493,9 @@ static void GenerateFastApiCall(MacroAssembler* masm, |
|
|
|
} else { |
|
|
|
__ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data)); |
|
|
|
} |
|
|
|
__ mov(Operand(esp, 4 * kPointerSize), |
|
|
|
Immediate(reinterpret_cast<int>(masm->isolate()))); |
|
|
|
|
|
|
|
// Prepare arguments.
|
|
|
|
__ lea(eax, Operand(esp, 4 * kPointerSize)); |
|
|
|
__ lea(eax, Operand(esp, 3 * kPointerSize)); |
|
|
|
|
|
|
|
const int kApiArgc = 1; // API function gets reference to the v8::Arguments.
|
|
|
|
|
|
|
@ -683,7 +679,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { |
|
|
|
__ CallExternalReference( |
|
|
|
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
|
|
|
masm->isolate()), |
|
|
|
6); |
|
|
|
5); |
|
|
|
|
|
|
|
// Restore the name_ register.
|
|
|
|
__ pop(name_); |
|
|
@ -1038,7 +1034,6 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, |
|
|
|
} else { |
|
|
|
__ push(Immediate(Handle<Object>(callback->data()))); |
|
|
|
} |
|
|
|
__ push(Immediate(reinterpret_cast<int>(isolate()))); |
|
|
|
|
|
|
|
// Save a pointer to where we pushed the arguments pointer.
|
|
|
|
// This will be passed as the const AccessorInfo& to the C++ callback.
|
|
|
@ -1049,9 +1044,9 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, |
|
|
|
|
|
|
|
__ push(scratch3); // Restore return address.
|
|
|
|
|
|
|
|
// 4 elements array for v8::Arguments::values_, handler for name and pointer
|
|
|
|
// 3 elements array for v8::Arguments::values_, handler for name and pointer
|
|
|
|
// to the values (it considered as smi in GC).
|
|
|
|
const int kStackSpace = 6; |
|
|
|
const int kStackSpace = 5; |
|
|
|
const int kApiArgc = 2; |
|
|
|
|
|
|
|
__ PrepareCallApiFunction(kApiArgc); |
|
|
@ -1218,7 +1213,6 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, |
|
|
|
__ push(holder_reg); |
|
|
|
__ mov(holder_reg, Immediate(callback)); |
|
|
|
__ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); |
|
|
|
__ push(Immediate(reinterpret_cast<int>(isolate()))); |
|
|
|
__ push(holder_reg); |
|
|
|
__ push(name_reg); |
|
|
|
__ push(scratch2); // restore return address
|
|
|
@ -1226,7 +1220,7 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, |
|
|
|
ExternalReference ref = |
|
|
|
ExternalReference(IC_Utility(IC::kLoadCallbackProperty), |
|
|
|
masm()->isolate()); |
|
|
|
__ TailCallExternalReference(ref, 6, 1); |
|
|
|
__ TailCallExternalReference(ref, 5, 1); |
|
|
|
} |
|
|
|
} else { // !compile_followup_inline
|
|
|
|
// Call the runtime system to load the interceptor.
|
|
|
@ -1242,7 +1236,7 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, |
|
|
|
ExternalReference ref = |
|
|
|
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
|
|
|
isolate()); |
|
|
|
__ TailCallExternalReference(ref, 6, 1); |
|
|
|
__ TailCallExternalReference(ref, 5, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -2180,7 +2174,7 @@ Handle<Code> CallStubCompiler::CompileFastApiCall( |
|
|
|
name, depth, &miss); |
|
|
|
|
|
|
|
// Move the return address on top of the stack.
|
|
|
|
__ mov(eax, Operand(esp, 4 * kPointerSize)); |
|
|
|
__ mov(eax, Operand(esp, 3 * kPointerSize)); |
|
|
|
__ mov(Operand(esp, 0 * kPointerSize), eax); |
|
|
|
|
|
|
|
// esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
|
|
|
@ -2709,27 +2703,27 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, |
|
|
|
Handle<JSObject> object, |
|
|
|
Handle<JSObject> last) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- eax : receiver
|
|
|
|
// -- ecx : name
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
|
Label miss; |
|
|
|
|
|
|
|
// Check that the receiver isn't a smi.
|
|
|
|
__ JumpIfSmi(edx, &miss); |
|
|
|
__ JumpIfSmi(eax, &miss); |
|
|
|
|
|
|
|
ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
|
|
|
|
|
|
|
// Check the maps of the full prototype chain. Also check that
|
|
|
|
// global property cells up to (but not including) the last object
|
|
|
|
// in the prototype chain are empty.
|
|
|
|
CheckPrototypes(object, edx, last, ebx, eax, edi, name, &miss); |
|
|
|
CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
|
|
|
|
|
|
|
// If the last object in the prototype chain is a global object,
|
|
|
|
// check that the global property cell is empty.
|
|
|
|
if (last->IsGlobalObject()) { |
|
|
|
GenerateCheckPropertyCell( |
|
|
|
masm(), Handle<GlobalObject>::cast(last), name, eax, &miss); |
|
|
|
masm(), Handle<GlobalObject>::cast(last), name, edx, &miss); |
|
|
|
} |
|
|
|
|
|
|
|
// Return undefined if maps of the full prototype chain are still the
|
|
|
@ -2750,13 +2744,13 @@ Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, |
|
|
|
int index, |
|
|
|
Handle<String> name) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- eax : receiver
|
|
|
|
// -- ecx : name
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
|
Label miss; |
|
|
|
|
|
|
|
GenerateLoadField(object, holder, edx, ebx, eax, edi, index, name, &miss); |
|
|
|
GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); |
|
|
|
__ bind(&miss); |
|
|
|
GenerateLoadMiss(masm(), Code::LOAD_IC); |
|
|
|
|
|
|
@ -2771,13 +2765,13 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback( |
|
|
|
Handle<JSObject> holder, |
|
|
|
Handle<AccessorInfo> callback) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- eax : receiver
|
|
|
|
// -- ecx : name
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
|
Label miss; |
|
|
|
|
|
|
|
GenerateLoadCallback(object, holder, edx, ecx, ebx, eax, edi, callback, |
|
|
|
GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, callback, |
|
|
|
name, &miss); |
|
|
|
__ bind(&miss); |
|
|
|
GenerateLoadMiss(masm(), Code::LOAD_IC); |
|
|
@ -2792,13 +2786,13 @@ Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
|
|
|
Handle<JSFunction> value, |
|
|
|
Handle<String> name) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- eax : receiver
|
|
|
|
// -- ecx : name
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
|
Label miss; |
|
|
|
|
|
|
|
GenerateLoadConstant(object, holder, edx, ebx, eax, edi, value, name, &miss); |
|
|
|
GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); |
|
|
|
__ bind(&miss); |
|
|
|
GenerateLoadMiss(masm(), Code::LOAD_IC); |
|
|
|
|
|
|
@ -2811,8 +2805,8 @@ Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, |
|
|
|
Handle<JSObject> holder, |
|
|
|
Handle<String> name) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- eax : receiver
|
|
|
|
// -- ecx : name
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
|
Label miss; |
|
|
@ -2822,7 +2816,7 @@ Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, |
|
|
|
|
|
|
|
// TODO(368): Compile in the whole chain: all the interceptors in
|
|
|
|
// prototypes and ultimate answer.
|
|
|
|
GenerateLoadInterceptor(receiver, holder, &lookup, edx, ecx, eax, ebx, edi, |
|
|
|
GenerateLoadInterceptor(receiver, holder, &lookup, eax, ecx, edx, ebx, edi, |
|
|
|
name, &miss); |
|
|
|
|
|
|
|
__ bind(&miss); |
|
|
@ -2840,15 +2834,15 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
|
|
|
Handle<String> name, |
|
|
|
bool is_dont_delete) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- eax : receiver
|
|
|
|
// -- ecx : name
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
|
Label miss; |
|
|
|
|
|
|
|
// Check that the maps haven't changed.
|
|
|
|
__ JumpIfSmi(edx, &miss); |
|
|
|
CheckPrototypes(object, edx, holder, ebx, eax, edi, name, &miss); |
|
|
|
__ JumpIfSmi(eax, &miss); |
|
|
|
CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); |
|
|
|
|
|
|
|
// Get the value from the cell.
|
|
|
|
if (Serializer::enabled()) { |
|
|
@ -2886,7 +2880,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, |
|
|
|
Handle<JSObject> holder, |
|
|
|
int index) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -2896,10 +2890,10 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, |
|
|
|
__ IncrementCounter(counters->keyed_load_field(), 1); |
|
|
|
|
|
|
|
// Check that the name has not changed.
|
|
|
|
__ cmp(ecx, Immediate(name)); |
|
|
|
__ cmp(eax, Immediate(name)); |
|
|
|
__ j(not_equal, &miss); |
|
|
|
|
|
|
|
GenerateLoadField(receiver, holder, edx, ebx, eax, edi, index, name, &miss); |
|
|
|
GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
|
|
|
|
|
|
|
__ bind(&miss); |
|
|
|
__ DecrementCounter(counters->keyed_load_field(), 1); |
|
|
@ -2916,7 +2910,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( |
|
|
|
Handle<JSObject> holder, |
|
|
|
Handle<AccessorInfo> callback) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -2926,10 +2920,10 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( |
|
|
|
__ IncrementCounter(counters->keyed_load_callback(), 1); |
|
|
|
|
|
|
|
// Check that the name has not changed.
|
|
|
|
__ cmp(ecx, Immediate(name)); |
|
|
|
__ cmp(eax, Immediate(name)); |
|
|
|
__ j(not_equal, &miss); |
|
|
|
|
|
|
|
GenerateLoadCallback(receiver, holder, edx, ecx, ebx, eax, edi, callback, |
|
|
|
GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, callback, |
|
|
|
name, &miss); |
|
|
|
|
|
|
|
__ bind(&miss); |
|
|
@ -2947,7 +2941,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
|
|
|
Handle<JSObject> holder, |
|
|
|
Handle<JSFunction> value) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -2957,11 +2951,11 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
|
|
|
__ IncrementCounter(counters->keyed_load_constant_function(), 1); |
|
|
|
|
|
|
|
// Check that the name has not changed.
|
|
|
|
__ cmp(ecx, Immediate(name)); |
|
|
|
__ cmp(eax, Immediate(name)); |
|
|
|
__ j(not_equal, &miss); |
|
|
|
|
|
|
|
GenerateLoadConstant( |
|
|
|
receiver, holder, edx, ebx, eax, edi, value, name, &miss); |
|
|
|
receiver, holder, edx, ebx, ecx, edi, value, name, &miss); |
|
|
|
__ bind(&miss); |
|
|
|
__ DecrementCounter(counters->keyed_load_constant_function(), 1); |
|
|
|
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
|
|
@ -2976,7 +2970,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
|
|
|
Handle<JSObject> holder, |
|
|
|
Handle<String> name) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -2986,12 +2980,12 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
|
|
|
__ IncrementCounter(counters->keyed_load_interceptor(), 1); |
|
|
|
|
|
|
|
// Check that the name has not changed.
|
|
|
|
__ cmp(ecx, Immediate(name)); |
|
|
|
__ cmp(eax, Immediate(name)); |
|
|
|
__ j(not_equal, &miss); |
|
|
|
|
|
|
|
LookupResult lookup(isolate()); |
|
|
|
LookupPostInterceptor(holder, name, &lookup); |
|
|
|
GenerateLoadInterceptor(receiver, holder, &lookup, edx, ecx, eax, ebx, edi, |
|
|
|
GenerateLoadInterceptor(receiver, holder, &lookup, edx, eax, ecx, ebx, edi, |
|
|
|
name, &miss); |
|
|
|
__ bind(&miss); |
|
|
|
__ DecrementCounter(counters->keyed_load_interceptor(), 1); |
|
|
@ -3005,7 +2999,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
|
|
|
Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
|
|
|
Handle<String> name) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3015,10 +3009,10 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
|
|
|
__ IncrementCounter(counters->keyed_load_array_length(), 1); |
|
|
|
|
|
|
|
// Check that the name has not changed.
|
|
|
|
__ cmp(ecx, Immediate(name)); |
|
|
|
__ cmp(eax, Immediate(name)); |
|
|
|
__ j(not_equal, &miss); |
|
|
|
|
|
|
|
GenerateLoadArrayLength(masm(), edx, eax, &miss); |
|
|
|
GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
|
|
|
__ bind(&miss); |
|
|
|
__ DecrementCounter(counters->keyed_load_array_length(), 1); |
|
|
|
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
|
|
@ -3031,7 +3025,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
|
|
|
Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( |
|
|
|
Handle<String> name) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3041,10 +3035,10 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( |
|
|
|
__ IncrementCounter(counters->keyed_load_string_length(), 1); |
|
|
|
|
|
|
|
// Check that the name has not changed.
|
|
|
|
__ cmp(ecx, Immediate(name)); |
|
|
|
__ cmp(eax, Immediate(name)); |
|
|
|
__ j(not_equal, &miss); |
|
|
|
|
|
|
|
GenerateLoadStringLength(masm(), edx, eax, ebx, &miss, true); |
|
|
|
GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
|
|
|
__ bind(&miss); |
|
|
|
__ DecrementCounter(counters->keyed_load_string_length(), 1); |
|
|
|
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
|
|
@ -3057,7 +3051,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( |
|
|
|
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( |
|
|
|
Handle<String> name) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3067,10 +3061,10 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( |
|
|
|
__ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
|
|
|
|
|
|
|
// Check that the name has not changed.
|
|
|
|
__ cmp(ecx, Immediate(name)); |
|
|
|
__ cmp(eax, Immediate(name)); |
|
|
|
__ j(not_equal, &miss); |
|
|
|
|
|
|
|
GenerateLoadFunctionPrototype(masm(), edx, eax, ebx, &miss); |
|
|
|
GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
|
|
|
__ bind(&miss); |
|
|
|
__ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
|
|
|
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
|
|
@ -3083,7 +3077,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( |
|
|
|
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
|
|
|
Handle<Map> receiver_map) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3104,7 +3098,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
|
|
|
MapHandleList* receiver_maps, |
|
|
|
CodeHandleList* handler_ics) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3268,7 +3262,7 @@ Handle<Code> ConstructStubCompiler::CompileConstructStub( |
|
|
|
void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( |
|
|
|
MacroAssembler* masm) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3276,15 +3270,21 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( |
|
|
|
|
|
|
|
// 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(ecx, &miss_force_generic); |
|
|
|
__ mov(ebx, ecx); |
|
|
|
__ JumpIfNotSmi(eax, &miss_force_generic); |
|
|
|
__ mov(ebx, eax); |
|
|
|
__ SmiUntag(ebx); |
|
|
|
__ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); |
|
|
|
__ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
|
|
|
|
|
|
|
// Push receiver on the stack to free up a register for the dictionary
|
|
|
|
// probing.
|
|
|
|
__ push(edx); |
|
|
|
__ LoadFromNumberDictionary(&slow, eax, ecx, ebx, edx, edi, eax); |
|
|
|
__ LoadFromNumberDictionary(&slow, |
|
|
|
ecx, |
|
|
|
eax, |
|
|
|
ebx, |
|
|
|
edx, |
|
|
|
edi, |
|
|
|
eax); |
|
|
|
// Pop receiver before returning.
|
|
|
|
__ pop(edx); |
|
|
|
__ ret(0); |
|
|
@ -3293,6 +3293,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( |
|
|
|
__ pop(edx); |
|
|
|
|
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- eax : value
|
|
|
|
// -- ecx : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
@ -3304,6 +3305,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( |
|
|
|
|
|
|
|
__ bind(&miss_force_generic); |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- eax : value
|
|
|
|
// -- ecx : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
@ -3315,44 +3317,11 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void GenerateSmiKeyCheck(MacroAssembler* masm, |
|
|
|
Register key, |
|
|
|
Register scratch, |
|
|
|
XMMRegister xmm_scratch0, |
|
|
|
XMMRegister xmm_scratch1, |
|
|
|
Label* fail) { |
|
|
|
// Check that key is a smi and if SSE2 is available a heap number
|
|
|
|
// containing a smi and branch if the check fails.
|
|
|
|
if (CpuFeatures::IsSupported(SSE2)) { |
|
|
|
CpuFeatures::Scope use_sse2(SSE2); |
|
|
|
Label key_ok; |
|
|
|
__ JumpIfSmi(key, &key_ok); |
|
|
|
__ cmp(FieldOperand(key, HeapObject::kMapOffset), |
|
|
|
Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map()))); |
|
|
|
__ j(not_equal, fail); |
|
|
|
__ movdbl(xmm_scratch0, FieldOperand(key, HeapNumber::kValueOffset)); |
|
|
|
__ cvttsd2si(scratch, Operand(xmm_scratch0)); |
|
|
|
__ cvtsi2sd(xmm_scratch1, scratch); |
|
|
|
__ ucomisd(xmm_scratch1, xmm_scratch0); |
|
|
|
__ j(not_equal, fail); |
|
|
|
__ j(parity_even, fail); // NaN.
|
|
|
|
// Check if the key fits in the smi range.
|
|
|
|
__ cmp(scratch, 0xc0000000); |
|
|
|
__ j(sign, fail); |
|
|
|
__ SmiTag(scratch); |
|
|
|
__ mov(key, scratch); |
|
|
|
__ bind(&key_ok); |
|
|
|
} else { |
|
|
|
__ JumpIfNotSmi(key, fail); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
|
|
|
MacroAssembler* masm, |
|
|
|
ElementsKind elements_kind) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3361,41 +3330,41 @@ 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 or a heap number convertible to a smi.
|
|
|
|
GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); |
|
|
|
// Check that the key is a smi.
|
|
|
|
__ JumpIfNotSmi(eax, &miss_force_generic); |
|
|
|
|
|
|
|
// Check that the index is in range.
|
|
|
|
__ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
|
|
|
__ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); |
|
|
|
__ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset)); |
|
|
|
// Unsigned comparison catches both negative and too-large values.
|
|
|
|
__ j(above_equal, &miss_force_generic); |
|
|
|
__ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); |
|
|
|
// ebx: base pointer of external storage
|
|
|
|
switch (elements_kind) { |
|
|
|
case EXTERNAL_BYTE_ELEMENTS: |
|
|
|
__ SmiUntag(ecx); // Untag the index.
|
|
|
|
__ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); |
|
|
|
__ SmiUntag(eax); // Untag the index.
|
|
|
|
__ movsx_b(eax, Operand(ebx, eax, times_1, 0)); |
|
|
|
break; |
|
|
|
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
|
|
|
case EXTERNAL_PIXEL_ELEMENTS: |
|
|
|
__ SmiUntag(ecx); // Untag the index.
|
|
|
|
__ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); |
|
|
|
__ SmiUntag(eax); // Untag the index.
|
|
|
|
__ movzx_b(eax, Operand(ebx, eax, times_1, 0)); |
|
|
|
break; |
|
|
|
case EXTERNAL_SHORT_ELEMENTS: |
|
|
|
__ movsx_w(eax, Operand(ebx, ecx, times_1, 0)); |
|
|
|
__ movsx_w(eax, Operand(ebx, eax, times_1, 0)); |
|
|
|
break; |
|
|
|
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
|
|
|
__ movzx_w(eax, Operand(ebx, ecx, times_1, 0)); |
|
|
|
__ movzx_w(eax, Operand(ebx, eax, times_1, 0)); |
|
|
|
break; |
|
|
|
case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
|
|
|
case EXTERNAL_INT_ELEMENTS: |
|
|
|
__ mov(eax, Operand(ebx, ecx, times_2, 0)); |
|
|
|
__ mov(ecx, Operand(ebx, eax, times_2, 0)); |
|
|
|
break; |
|
|
|
case EXTERNAL_FLOAT_ELEMENTS: |
|
|
|
__ fld_s(Operand(ebx, ecx, times_2, 0)); |
|
|
|
__ fld_s(Operand(ebx, eax, times_2, 0)); |
|
|
|
break; |
|
|
|
case EXTERNAL_DOUBLE_ELEMENTS: |
|
|
|
__ fld_d(Operand(ebx, ecx, times_4, 0)); |
|
|
|
__ fld_d(Operand(ebx, eax, times_4, 0)); |
|
|
|
break; |
|
|
|
default: |
|
|
|
UNREACHABLE(); |
|
|
@ -3403,7 +3372,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
|
|
|
} |
|
|
|
|
|
|
|
// For integer array types:
|
|
|
|
// eax: value
|
|
|
|
// ecx: value
|
|
|
|
// For floating-point array type:
|
|
|
|
// FP(0): value
|
|
|
|
|
|
|
@ -3414,17 +3383,18 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
|
|
|
// it to a HeapNumber.
|
|
|
|
Label box_int; |
|
|
|
if (elements_kind == EXTERNAL_INT_ELEMENTS) { |
|
|
|
__ cmp(eax, 0xc0000000); |
|
|
|
__ cmp(ecx, 0xC0000000); |
|
|
|
__ j(sign, &box_int); |
|
|
|
} else { |
|
|
|
ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); |
|
|
|
// The test is different for unsigned int values. Since we need
|
|
|
|
// the value to be in the range of a positive smi, we can't
|
|
|
|
// handle either of the top two bits being set in the value.
|
|
|
|
__ test(eax, Immediate(0xc0000000)); |
|
|
|
__ test(ecx, Immediate(0xC0000000)); |
|
|
|
__ j(not_zero, &box_int); |
|
|
|
} |
|
|
|
|
|
|
|
__ mov(eax, ecx); |
|
|
|
__ SmiTag(eax); |
|
|
|
__ ret(0); |
|
|
|
|
|
|
@ -3433,31 +3403,33 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
|
|
|
// Allocate a HeapNumber for the int and perform int-to-double
|
|
|
|
// conversion.
|
|
|
|
if (elements_kind == EXTERNAL_INT_ELEMENTS) { |
|
|
|
__ push(eax); |
|
|
|
__ push(ecx); |
|
|
|
__ fild_s(Operand(esp, 0)); |
|
|
|
__ pop(eax); |
|
|
|
__ pop(ecx); |
|
|
|
} else { |
|
|
|
ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); |
|
|
|
// Need to zero-extend the value.
|
|
|
|
// There's no fild variant for unsigned values, so zero-extend
|
|
|
|
// to a 64-bit int manually.
|
|
|
|
__ push(Immediate(0)); |
|
|
|
__ push(eax); |
|
|
|
__ push(ecx); |
|
|
|
__ fild_d(Operand(esp, 0)); |
|
|
|
__ pop(eax); |
|
|
|
__ pop(eax); |
|
|
|
__ pop(ecx); |
|
|
|
__ pop(ecx); |
|
|
|
} |
|
|
|
// FP(0): value
|
|
|
|
__ AllocateHeapNumber(eax, ebx, edi, &failed_allocation); |
|
|
|
__ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); |
|
|
|
// Set the value.
|
|
|
|
__ mov(eax, ecx); |
|
|
|
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
|
|
|
__ ret(0); |
|
|
|
} else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
|
|
|
elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
|
|
|
// For the floating-point array type, we need to always allocate a
|
|
|
|
// HeapNumber.
|
|
|
|
__ AllocateHeapNumber(eax, ebx, edi, &failed_allocation); |
|
|
|
__ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); |
|
|
|
// Set the value.
|
|
|
|
__ mov(eax, ecx); |
|
|
|
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
|
|
|
__ ret(0); |
|
|
|
} else { |
|
|
@ -3477,7 +3449,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
|
|
|
__ IncrementCounter(counters->keyed_load_external_array_slow(), 1); |
|
|
|
|
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3486,7 +3458,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
|
|
|
__ jmp(ic, RelocInfo::CODE_TARGET); |
|
|
|
|
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3503,8 +3475,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
|
|
|
MacroAssembler* masm, |
|
|
|
ElementsKind elements_kind) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- eax : value
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3513,8 +3484,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 or a heap number convertible to a smi.
|
|
|
|
GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic); |
|
|
|
// Check that the key is a smi.
|
|
|
|
__ JumpIfNotSmi(ecx, &miss_force_generic); |
|
|
|
|
|
|
|
// Check that the index is in range.
|
|
|
|
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
|
|
@ -3609,39 +3580,12 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
|
|
|
// (code-stubs-ia32.cc) is roughly what is needed here though the
|
|
|
|
// conversion failure case does not need to be handled.
|
|
|
|
if (CpuFeatures::IsSupported(SSE2)) { |
|
|
|
if ((elements_kind == EXTERNAL_INT_ELEMENTS || |
|
|
|
elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) && |
|
|
|
CpuFeatures::IsSupported(SSE3)) { |
|
|
|
CpuFeatures::Scope scope(SSE3); |
|
|
|
// fisttp stores values as signed integers. To represent the
|
|
|
|
// entire range of int and unsigned int arrays, store as a
|
|
|
|
// 64-bit int and discard the high 32 bits.
|
|
|
|
__ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
|
|
|
__ sub(esp, Immediate(2 * kPointerSize)); |
|
|
|
__ fisttp_d(Operand(esp, 0)); |
|
|
|
|
|
|
|
// If conversion failed (NaN, infinity, or a number outside
|
|
|
|
// signed int64 range), the result is 0x8000000000000000, and
|
|
|
|
// we must handle this case in the runtime.
|
|
|
|
Label ok; |
|
|
|
__ cmp(Operand(esp, kPointerSize), Immediate(0x80000000u)); |
|
|
|
__ j(not_equal, &ok); |
|
|
|
__ cmp(Operand(esp, 0), Immediate(0)); |
|
|
|
__ j(not_equal, &ok); |
|
|
|
__ add(esp, Immediate(2 * kPointerSize)); // Restore the stack.
|
|
|
|
__ jmp(&slow); |
|
|
|
|
|
|
|
__ bind(&ok); |
|
|
|
__ pop(ebx); |
|
|
|
__ add(esp, Immediate(kPointerSize)); |
|
|
|
__ mov(Operand(edi, ecx, times_2, 0), ebx); |
|
|
|
} else { |
|
|
|
if (elements_kind != EXTERNAL_INT_ELEMENTS && |
|
|
|
elements_kind != EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
|
|
|
ASSERT(CpuFeatures::IsSupported(SSE2)); |
|
|
|
CpuFeatures::Scope scope(SSE2); |
|
|
|
__ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset)); |
|
|
|
__ cmp(ebx, 0x80000000u); |
|
|
|
__ j(equal, &slow); |
|
|
|
// ebx: untagged integer value
|
|
|
|
// ecx: untagged integer value
|
|
|
|
switch (elements_kind) { |
|
|
|
case EXTERNAL_PIXEL_ELEMENTS: |
|
|
|
__ ClampUint8(ebx); |
|
|
@ -3655,14 +3599,41 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
|
|
|
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
|
|
|
__ mov_w(Operand(edi, ecx, times_1, 0), ebx); |
|
|
|
break; |
|
|
|
case EXTERNAL_INT_ELEMENTS: |
|
|
|
case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
|
|
|
__ mov(Operand(edi, ecx, times_2, 0), ebx); |
|
|
|
break; |
|
|
|
default: |
|
|
|
UNREACHABLE(); |
|
|
|
break; |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (CpuFeatures::IsSupported(SSE3)) { |
|
|
|
CpuFeatures::Scope scope(SSE3); |
|
|
|
// fisttp stores values as signed integers. To represent the
|
|
|
|
// entire range of int and unsigned int arrays, store as a
|
|
|
|
// 64-bit int and discard the high 32 bits.
|
|
|
|
// If the value is NaN or +/-infinity, the result is 0x80000000,
|
|
|
|
// which is automatically zero when taken mod 2^n, n < 32.
|
|
|
|
__ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
|
|
|
__ sub(esp, Immediate(2 * kPointerSize)); |
|
|
|
__ fisttp_d(Operand(esp, 0)); |
|
|
|
__ pop(ebx); |
|
|
|
__ add(esp, Immediate(kPointerSize)); |
|
|
|
} else { |
|
|
|
ASSERT(CpuFeatures::IsSupported(SSE2)); |
|
|
|
CpuFeatures::Scope scope(SSE2); |
|
|
|
// We can easily implement the correct rounding behavior for the
|
|
|
|
// range [0, 2^31-1]. For the time being, to keep this code simple,
|
|
|
|
// make the slow runtime call for values outside this range.
|
|
|
|
// Note: we could do better for signed int arrays.
|
|
|
|
__ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
|
|
|
// We will need the key if we have to make the slow runtime call.
|
|
|
|
__ push(ebx); |
|
|
|
__ LoadPowerOf2(xmm1, ebx, 31); |
|
|
|
__ pop(ebx); |
|
|
|
__ ucomisd(xmm1, xmm0); |
|
|
|
__ j(above_equal, &slow); |
|
|
|
__ cvttsd2si(ebx, Operand(xmm0)); |
|
|
|
} |
|
|
|
// ebx: untagged integer value
|
|
|
|
__ mov(Operand(edi, ecx, times_2, 0), ebx); |
|
|
|
} |
|
|
|
__ ret(0); // Return original value.
|
|
|
|
} |
|
|
@ -3700,7 +3671,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
|
|
|
|
|
|
|
void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3709,19 +3680,19 @@ 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 or a heap number convertible to a smi.
|
|
|
|
GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); |
|
|
|
// Check that the key is a smi.
|
|
|
|
__ JumpIfNotSmi(eax, &miss_force_generic); |
|
|
|
|
|
|
|
// Get the elements array.
|
|
|
|
__ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); |
|
|
|
__ AssertFastElements(eax); |
|
|
|
__ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
|
|
|
__ AssertFastElements(ecx); |
|
|
|
|
|
|
|
// Check that the key is within bounds.
|
|
|
|
__ cmp(ecx, FieldOperand(eax, FixedArray::kLengthOffset)); |
|
|
|
__ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
|
|
|
__ j(above_equal, &miss_force_generic); |
|
|
|
|
|
|
|
// Load the result and make sure it's not the hole.
|
|
|
|
__ mov(ebx, Operand(eax, ecx, times_2, |
|
|
|
__ mov(ebx, Operand(ecx, eax, times_2, |
|
|
|
FixedArray::kHeaderSize - kHeapObjectTag)); |
|
|
|
__ cmp(ebx, masm->isolate()->factory()->the_hole_value()); |
|
|
|
__ j(equal, &miss_force_generic); |
|
|
@ -3738,7 +3709,7 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { |
|
|
|
void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( |
|
|
|
MacroAssembler* masm) { |
|
|
|
// ----------- S t a t e -------------
|
|
|
|
// -- ecx : key
|
|
|
|
// -- eax : key
|
|
|
|
// -- edx : receiver
|
|
|
|
// -- esp[0] : return address
|
|
|
|
// -----------------------------------
|
|
|
@ -3747,38 +3718,39 @@ 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 or a heap number convertible to a smi.
|
|
|
|
GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); |
|
|
|
// Check that the key is a smi.
|
|
|
|
__ JumpIfNotSmi(eax, &miss_force_generic); |
|
|
|
|
|
|
|
// Get the elements array.
|
|
|
|
__ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); |
|
|
|
__ AssertFastElements(eax); |
|
|
|
__ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
|
|
|
__ AssertFastElements(ecx); |
|
|
|
|
|
|
|
// Check that the key is within bounds.
|
|
|
|
__ cmp(ecx, FieldOperand(eax, FixedDoubleArray::kLengthOffset)); |
|
|
|
__ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset)); |
|
|
|
__ j(above_equal, &miss_force_generic); |
|
|
|
|
|
|
|
// Check for the hole
|
|
|
|
uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); |
|
|
|
__ cmp(FieldOperand(eax, ecx, times_4, offset), Immediate(kHoleNanUpper32)); |
|
|
|
__ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32)); |
|
|
|
__ j(equal, &miss_force_generic); |
|
|
|
|
|
|
|
// Always allocate a heap number for the result.
|
|
|
|
if (CpuFeatures::IsSupported(SSE2)) { |
|
|
|
CpuFeatures::Scope use_sse2(SSE2); |
|
|
|
__ movdbl(xmm0, FieldOperand(eax, ecx, times_4, |
|
|
|
__ movdbl(xmm0, FieldOperand(ecx, eax, times_4, |
|
|
|
FixedDoubleArray::kHeaderSize)); |
|
|
|
} else { |
|
|
|
__ fld_d(FieldOperand(eax, ecx, times_4, FixedDoubleArray::kHeaderSize)); |
|
|
|
__ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize)); |
|
|
|
} |
|
|
|
__ AllocateHeapNumber(eax, ebx, edi, &slow_allocate_heapnumber); |
|
|
|
__ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber); |
|
|
|
// Set the value.
|
|
|
|
if (CpuFeatures::IsSupported(SSE2)) { |
|
|
|
CpuFeatures::Scope use_sse2(SSE2); |
|
|
|
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
|
|
|
__ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); |
|
|
|
} else { |
|
|
|
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
|
|
|
__ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset)); |
|
|
|
} |
|
|
|
__ mov(eax, ecx); |
|
|
|
__ ret(0); |
|
|
|
|
|
|
|
__ bind(&slow_allocate_heapnumber); |
|
|
@ -3815,8 +3787,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 or a heap number convertible to a smi.
|
|
|
|
GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic); |
|
|
|
// Check that the key is a smi.
|
|
|
|
__ JumpIfNotSmi(ecx, &miss_force_generic); |
|
|
|
|
|
|
|
if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
|
|
|
__ JumpIfNotSmi(eax, &transition_elements_kind); |
|
|
@ -3970,8 +3942,8 @@ 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.
|
|
|
|
|
|
|
|
// Check that the key is a smi or a heap number convertible to a smi.
|
|
|
|
GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic); |
|
|
|
// Check that the key is a smi.
|
|
|
|
__ JumpIfNotSmi(ecx, &miss_force_generic); |
|
|
|
|
|
|
|
// Get the elements array.
|
|
|
|
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
|
|
@ -4032,7 +4004,6 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
|
|
|
|
|
|
|
int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements); |
|
|
|
__ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT); |
|
|
|
|
|
|
|
// Restore the key, which is known to be the array length.
|
|
|
|
__ mov(ecx, Immediate(0)); |
|
|
|
|
|
|
|