summaryrefslogtreecommitdiff
path: root/deps/v8/src/ia32/stub-cache-ia32.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ia32/stub-cache-ia32.cc')
-rw-r--r--deps/v8/src/ia32/stub-cache-ia32.cc401
1 files changed, 177 insertions, 224 deletions
diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc
index 07cb14d02..ab62764e6 100644
--- a/deps/v8/src/ia32/stub-cache-ia32.cc
+++ b/deps/v8/src/ia32/stub-cache-ia32.cc
@@ -66,8 +66,8 @@ static void ProbeTable(Isolate* isolate,
__ j(not_equal, &miss);
// Jump to the first instruction in the code stub.
- __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
- __ jmp(extra);
+ __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag));
+ __ jmp(Operand(extra));
__ bind(&miss);
} else {
@@ -92,8 +92,8 @@ static void ProbeTable(Isolate* isolate,
__ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
// Jump to the first instruction in the code stub.
- __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
- __ jmp(offset);
+ __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag));
+ __ jmp(Operand(offset));
// Pop at miss.
__ bind(&miss);
@@ -204,8 +204,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
__ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
__ xor_(scratch, flags);
__ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
- __ sub(scratch, name);
- __ add(scratch, Immediate(flags));
+ __ sub(scratch, Operand(name));
+ __ add(Operand(scratch), Immediate(flags));
__ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
// Probe the secondary table.
@@ -318,7 +318,7 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
Register scratch2,
Label* miss_label) {
__ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
- __ mov(eax, scratch1);
+ __ mov(eax, Operand(scratch1));
__ ret(0);
}
@@ -406,7 +406,7 @@ static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
// frame.
// -----------------------------------
__ pop(scratch);
- __ add(esp, Immediate(kPointerSize * kFastApiCallArguments));
+ __ add(Operand(esp), Immediate(kPointerSize * kFastApiCallArguments));
__ push(scratch);
}
@@ -462,7 +462,7 @@ static MaybeObject* GenerateFastApiCall(MacroAssembler* masm,
__ PrepareCallApiFunction(kApiArgc + kApiStackSpace);
__ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_.
- __ add(eax, Immediate(argc * kPointerSize));
+ __ add(Operand(eax), Immediate(argc * kPointerSize));
__ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_.
__ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_.
// v8::Arguments::is_construct_call_.
@@ -651,7 +651,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
scratch1, scratch2, scratch3, name,
miss_label);
- FrameScope scope(masm, StackFrame::INTERNAL);
+ __ EnterInternalFrame();
// Save the name_ register across the call.
__ push(name_);
@@ -668,8 +668,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
// Restore the name_ register.
__ pop(name_);
-
- // Leave the internal frame.
+ __ LeaveInternalFrame();
}
void LoadWithInterceptor(MacroAssembler* masm,
@@ -677,21 +676,19 @@ class CallInterceptorCompiler BASE_EMBEDDED {
Register holder,
JSObject* holder_obj,
Label* interceptor_succeeded) {
- {
- FrameScope scope(masm, StackFrame::INTERNAL);
- __ push(holder); // Save the holder.
- __ push(name_); // Save the name.
-
- CompileCallLoadPropertyWithInterceptor(masm,
- receiver,
- holder,
- name_,
- holder_obj);
-
- __ pop(name_); // Restore the name.
- __ pop(receiver); // Restore the holder.
- // Leave the internal frame.
- }
+ __ EnterInternalFrame();
+ __ push(holder); // Save the holder.
+ __ push(name_); // Save the name.
+
+ CompileCallLoadPropertyWithInterceptor(masm,
+ receiver,
+ holder,
+ name_,
+ holder_obj);
+
+ __ pop(name_); // Restore the name.
+ __ pop(receiver); // Restore the holder.
+ __ LeaveInternalFrame();
__ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel());
__ j(not_equal, interceptor_succeeded);
@@ -789,12 +786,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
- __ mov(name_reg, eax);
- __ RecordWriteField(receiver_reg,
- offset,
- name_reg,
- scratch,
- kDontSaveFPRegs);
+ __ mov(name_reg, Operand(eax));
+ __ RecordWrite(receiver_reg, offset, name_reg, scratch);
} else {
// Write to the properties array.
int offset = index * kPointerSize + FixedArray::kHeaderSize;
@@ -804,12 +797,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
- __ mov(name_reg, eax);
- __ RecordWriteField(scratch,
- offset,
- name_reg,
- receiver_reg,
- kDontSaveFPRegs);
+ __ mov(name_reg, Operand(eax));
+ __ RecordWrite(scratch, offset, name_reg, receiver_reg);
}
// Return the value (register eax).
@@ -943,7 +932,7 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
} else if (heap()->InNewSpace(prototype)) {
// Get the map of the current object.
__ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
- __ cmp(scratch1, Immediate(Handle<Map>(current->map())));
+ __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map())));
// Branch on the result of the map check.
__ j(not_equal, miss);
// Check access rights to the global object. This has to happen
@@ -1064,7 +1053,7 @@ MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
__ pop(scratch3); // Get return address to place it below.
__ push(receiver); // receiver
- __ mov(scratch2, esp);
+ __ mov(scratch2, Operand(esp));
ASSERT(!scratch2.is(reg));
__ push(reg); // holder
// Push data from AccessorInfo.
@@ -1095,7 +1084,7 @@ MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
__ PrepareCallApiFunction(kApiArgc);
__ mov(ApiParameterOperand(0), ebx); // name.
- __ add(ebx, Immediate(kPointerSize));
+ __ add(Operand(ebx), Immediate(kPointerSize));
__ mov(ApiParameterOperand(1), ebx); // arguments pointer.
// Emitting a stub call may try to allocate (if the code is not
@@ -1169,43 +1158,41 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
// Save necessary data before invoking an interceptor.
// Requires a frame to make GC aware of pushed pointers.
- {
- FrameScope frame_scope(masm(), StackFrame::INTERNAL);
+ __ EnterInternalFrame();
- if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
- // CALLBACKS case needs a receiver to be passed into C++ callback.
- __ push(receiver);
- }
- __ push(holder_reg);
- __ push(name_reg);
-
- // Invoke an interceptor. Note: map checks from receiver to
- // interceptor's holder has been compiled before (see a caller
- // of this method.)
- CompileCallLoadPropertyWithInterceptor(masm(),
- receiver,
- holder_reg,
- name_reg,
- interceptor_holder);
-
- // Check if interceptor provided a value for property. If it's
- // the case, return immediately.
- Label interceptor_failed;
- __ cmp(eax, factory()->no_interceptor_result_sentinel());
- __ j(equal, &interceptor_failed);
- frame_scope.GenerateLeaveFrame();
- __ ret(0);
-
- __ bind(&interceptor_failed);
- __ pop(name_reg);
- __ pop(holder_reg);
- if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
- __ pop(receiver);
- }
+ if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
+ // CALLBACKS case needs a receiver to be passed into C++ callback.
+ __ push(receiver);
+ }
+ __ push(holder_reg);
+ __ push(name_reg);
+
+ // Invoke an interceptor. Note: map checks from receiver to
+ // interceptor's holder has been compiled before (see a caller
+ // of this method.)
+ CompileCallLoadPropertyWithInterceptor(masm(),
+ receiver,
+ holder_reg,
+ name_reg,
+ interceptor_holder);
+
+ // Check if interceptor provided a value for property. If it's
+ // the case, return immediately.
+ Label interceptor_failed;
+ __ cmp(eax, factory()->no_interceptor_result_sentinel());
+ __ j(equal, &interceptor_failed);
+ __ LeaveInternalFrame();
+ __ ret(0);
- // Leave the internal frame.
+ __ bind(&interceptor_failed);
+ __ pop(name_reg);
+ __ pop(holder_reg);
+ if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
+ __ pop(receiver);
}
+ __ LeaveInternalFrame();
+
// Check that the maps from interceptor's holder to lookup's holder
// haven't changed. And load lookup's holder into holder_reg.
if (interceptor_holder != lookup->holder()) {
@@ -1272,7 +1259,7 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
if (kind_ == Code::KEYED_CALL_IC) {
- __ cmp(ecx, Immediate(Handle<String>(name)));
+ __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
__ j(not_equal, miss);
}
}
@@ -1329,7 +1316,7 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
Immediate(Handle<SharedFunctionInfo>(function->shared())));
__ j(not_equal, miss);
} else {
- __ cmp(edi, Immediate(Handle<JSFunction>(function)));
+ __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function)));
__ j(not_equal, miss);
}
}
@@ -1454,25 +1441,21 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
__ j(not_equal, &call_builtin);
if (argc == 1) { // Otherwise fall through to call builtin.
- Label attempt_to_grow_elements, with_write_barrier;
+ Label exit, with_write_barrier, attempt_to_grow_elements;
// Get the array's length into eax and calculate new length.
__ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
STATIC_ASSERT(kSmiTagSize == 1);
STATIC_ASSERT(kSmiTag == 0);
- __ add(eax, Immediate(Smi::FromInt(argc)));
+ __ add(Operand(eax), Immediate(Smi::FromInt(argc)));
// Get the element's length into ecx.
__ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
// Check if we could survive without allocation.
- __ cmp(eax, ecx);
+ __ cmp(eax, Operand(ecx));
__ j(greater, &attempt_to_grow_elements);
- // Check if value is a smi.
- __ mov(ecx, Operand(esp, argc * kPointerSize));
- __ JumpIfNotSmi(ecx, &with_write_barrier);
-
// Save new length.
__ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
@@ -1480,27 +1463,20 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
__ lea(edx, FieldOperand(ebx,
eax, times_half_pointer_size,
FixedArray::kHeaderSize - argc * kPointerSize));
+ __ mov(ecx, Operand(esp, argc * kPointerSize));
__ mov(Operand(edx, 0), ecx);
+ // Check if value is a smi.
+ __ JumpIfNotSmi(ecx, &with_write_barrier);
+
+ __ bind(&exit);
__ ret((argc + 1) * kPointerSize);
__ bind(&with_write_barrier);
- __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
- __ CheckFastObjectElements(edi, &call_builtin);
-
- // Save new length.
- __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
-
- // Push the element.
- __ lea(edx, FieldOperand(ebx,
- eax, times_half_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize));
- __ mov(Operand(edx, 0), ecx);
-
- __ RecordWrite(
- ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+ __ InNewSpace(ebx, ecx, equal, &exit);
+ __ RecordWriteHelper(ebx, edx, ecx);
__ ret((argc + 1) * kPointerSize);
__ bind(&attempt_to_grow_elements);
@@ -1508,19 +1484,6 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
__ jmp(&call_builtin);
}
- __ mov(edi, Operand(esp, argc * kPointerSize));
- // Growing elements that are SMI-only requires special handling in case
- // the new element is non-Smi. For now, delegate to the builtin.
- Label no_fast_elements_check;
- __ JumpIfSmi(edi, &no_fast_elements_check);
- __ mov(esi, FieldOperand(edx, HeapObject::kMapOffset));
- __ CheckFastObjectElements(esi, &call_builtin, Label::kFar);
- __ bind(&no_fast_elements_check);
-
- // We could be lucky and the elements array could be at the top of
- // new-space. In this case we can just grow it in place by moving the
- // allocation pointer up.
-
ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address(isolate());
ExternalReference new_space_allocation_limit =
@@ -1534,43 +1497,33 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
__ lea(edx, FieldOperand(ebx,
eax, times_half_pointer_size,
FixedArray::kHeaderSize - argc * kPointerSize));
- __ cmp(edx, ecx);
+ __ cmp(edx, Operand(ecx));
__ j(not_equal, &call_builtin);
- __ add(ecx, Immediate(kAllocationDelta * kPointerSize));
+ __ add(Operand(ecx), Immediate(kAllocationDelta * kPointerSize));
__ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
__ j(above, &call_builtin);
// We fit and could grow elements.
__ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
+ __ mov(ecx, Operand(esp, argc * kPointerSize));
// Push the argument...
- __ mov(Operand(edx, 0), edi);
+ __ mov(Operand(edx, 0), ecx);
// ... and fill the rest with holes.
for (int i = 1; i < kAllocationDelta; i++) {
__ mov(Operand(edx, i * kPointerSize),
Immediate(factory()->the_hole_value()));
}
- // We know the elements array is in new space so we don't need the
- // remembered set, but we just pushed a value onto it so we may have to
- // tell the incremental marker to rescan the object that we just grew. We
- // don't need to worry about the holes because they are in old space and
- // already marked black.
- __ RecordWrite(ebx, edx, edi, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
-
// Restore receiver to edx as finish sequence assumes it's here.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
// Increment element's and array's sizes.
__ add(FieldOperand(ebx, FixedArray::kLengthOffset),
Immediate(Smi::FromInt(kAllocationDelta)));
-
- // NOTE: This only happen in new-space, where we don't
- // care about the black-byte-count on pages. Otherwise we should
- // update that too if the object is black.
-
__ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
+ // Elements are in new space, so write barrier is not required.
__ ret((argc + 1) * kPointerSize);
}
@@ -1632,7 +1585,7 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
// Get the array's length into ecx and calculate new length.
__ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset));
- __ sub(ecx, Immediate(Smi::FromInt(1)));
+ __ sub(Operand(ecx), Immediate(Smi::FromInt(1)));
__ j(negative, &return_undefined);
// Get the last element.
@@ -1641,7 +1594,7 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
__ mov(eax, FieldOperand(ebx,
ecx, times_half_pointer_size,
FixedArray::kHeaderSize));
- __ cmp(eax, Immediate(factory()->the_hole_value()));
+ __ cmp(Operand(eax), Immediate(factory()->the_hole_value()));
__ j(equal, &call_builtin);
// Set the array's length.
@@ -2105,10 +2058,10 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
__ sar(ebx, kBitsPerInt - 1);
// Do bitwise not or do nothing depending on ebx.
- __ xor_(eax, ebx);
+ __ xor_(eax, Operand(ebx));
// Add 1 or do nothing depending on ebx.
- __ sub(eax, ebx);
+ __ sub(eax, Operand(ebx));
// If the result is still negative, go to the slow case.
// This only happens for the most negative smi.
@@ -2191,7 +2144,7 @@ MaybeObject* CallStubCompiler::CompileFastApiCall(
// Allocate space for v8::Arguments implicit values. Must be initialized
// before calling any runtime function.
- __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize));
+ __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
// Check that the maps haven't changed and find a Holder as a side effect.
CheckPrototypes(JSObject::cast(object), edx, holder,
@@ -2207,7 +2160,7 @@ MaybeObject* CallStubCompiler::CompileFastApiCall(
if (result->IsFailure()) return result;
__ bind(&miss);
- __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
+ __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
__ bind(&miss_before_stack_reserved);
MaybeObject* maybe_result = GenerateMissBranch();
@@ -2646,9 +2599,13 @@ MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
Immediate(Handle<Map>(object->map())));
__ j(not_equal, &miss);
+
// Compute the cell operand to use.
- __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
- Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
+ Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell));
+ if (Serializer::enabled()) {
+ __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
+ cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
+ }
// Check that the value in the cell is not the hole. If it is, this
// cell could have been deleted and reintroducing the global needs
@@ -2659,23 +2616,8 @@ MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
// Store the value in the cell.
__ mov(cell_operand, eax);
- Label done;
- __ test(eax, Immediate(kSmiTagMask));
- __ j(zero, &done);
-
- __ mov(ecx, eax);
- __ lea(edx, cell_operand);
- // Cells are always in the remembered set.
- __ RecordWrite(ebx, // Object.
- edx, // Address.
- ecx, // Value.
- kDontSaveFPRegs,
- OMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
// Return the value (register eax).
- __ bind(&done);
-
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_store_global_inline(), 1);
__ ret(0);
@@ -2707,7 +2649,7 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
__ IncrementCounter(counters->keyed_store_field(), 1);
// Check that the name has not changed.
- __ cmp(ecx, Immediate(Handle<String>(name)));
+ __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
__ j(not_equal, &miss);
// Generate store field code. Trashes the name register.
@@ -2755,10 +2697,9 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) {
}
-MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic(
+MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
MapList* receiver_maps,
- CodeList* handler_stubs,
- MapList* transitioned_maps) {
+ CodeList* handler_ics) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
@@ -2766,21 +2707,15 @@ MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic(
// -- esp[0] : return address
// -----------------------------------
Label miss;
- __ JumpIfSmi(edx, &miss, Label::kNear);
- __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
- // ebx: receiver->map().
- for (int i = 0; i < receiver_maps->length(); ++i) {
- Handle<Map> map(receiver_maps->at(i));
- __ cmp(edi, map);
- if (transitioned_maps->at(i) == NULL) {
- __ j(equal, Handle<Code>(handler_stubs->at(i)));
- } else {
- Label next_map;
- __ j(not_equal, &next_map, Label::kNear);
- __ mov(ebx, Immediate(Handle<Map>(transitioned_maps->at(i))));
- __ jmp(Handle<Code>(handler_stubs->at(i)), RelocInfo::CODE_TARGET);
- __ bind(&next_map);
- }
+ __ JumpIfSmi(edx, &miss);
+
+ Register map_reg = ebx;
+ __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
+ int receiver_count = receiver_maps->length();
+ for (int current = 0; current < receiver_count; ++current) {
+ Handle<Map> map(receiver_maps->at(current));
+ __ cmp(map_reg, map);
+ __ j(equal, Handle<Code>(handler_ics->at(current)));
}
__ bind(&miss);
Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
@@ -3006,7 +2941,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
__ IncrementCounter(counters->keyed_load_field(), 1);
// Check that the name has not changed.
- __ cmp(eax, Immediate(Handle<String>(name)));
+ __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss);
GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss);
@@ -3036,7 +2971,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
__ IncrementCounter(counters->keyed_load_callback(), 1);
// Check that the name has not changed.
- __ cmp(eax, Immediate(Handle<String>(name)));
+ __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss);
MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx,
@@ -3071,7 +3006,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
__ IncrementCounter(counters->keyed_load_constant_function(), 1);
// Check that the name has not changed.
- __ cmp(eax, Immediate(Handle<String>(name)));
+ __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss);
GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi,
@@ -3099,7 +3034,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ IncrementCounter(counters->keyed_load_interceptor(), 1);
// Check that the name has not changed.
- __ cmp(eax, Immediate(Handle<String>(name)));
+ __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss);
LookupResult lookup;
@@ -3135,7 +3070,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
__ IncrementCounter(counters->keyed_load_array_length(), 1);
// Check that the name has not changed.
- __ cmp(eax, Immediate(Handle<String>(name)));
+ __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss);
GenerateLoadArrayLength(masm(), edx, ecx, &miss);
@@ -3160,7 +3095,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
__ IncrementCounter(counters->keyed_load_string_length(), 1);
// Check that the name has not changed.
- __ cmp(eax, Immediate(Handle<String>(name)));
+ __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss);
GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true);
@@ -3185,7 +3120,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
__ IncrementCounter(counters->keyed_load_function_prototype(), 1);
// Check that the name has not changed.
- __ cmp(eax, Immediate(Handle<String>(name)));
+ __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss);
GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
@@ -3220,7 +3155,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) {
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic(
+MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
MapList* receiver_maps,
CodeList* handler_ics) {
// ----------- S t a t e -------------
@@ -3363,7 +3298,7 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
// Move argc to ebx and retrieve and tag the JSObject to return.
__ mov(ebx, eax);
__ pop(eax);
- __ or_(eax, Immediate(kHeapObjectTag));
+ __ or_(Operand(eax), Immediate(kHeapObjectTag));
// Remove caller arguments and receiver from the stack and return.
__ pop(ecx);
@@ -3744,10 +3679,10 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// 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));
+ __ sub(Operand(esp), Immediate(2 * kPointerSize));
__ fisttp_d(Operand(esp, 0));
__ pop(ebx);
- __ add(esp, Immediate(kPointerSize));
+ __ add(Operand(esp), Immediate(kPointerSize));
} else {
ASSERT(CpuFeatures::IsSupported(SSE2));
CpuFeatures::Scope scope(SSE2);
@@ -3903,17 +3838,15 @@ void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
}
-void KeyedStoreStubCompiler::GenerateStoreFastElement(
- MacroAssembler* masm,
- bool is_js_array,
- ElementsKind elements_kind) {
+void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
+ bool is_js_array) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
- Label miss_force_generic, transition_elements_kind;
+ Label miss_force_generic;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
@@ -3937,28 +3870,11 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
__ j(above_equal, &miss_force_generic);
}
- if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
- __ JumpIfNotSmi(eax, &transition_elements_kind);
- // ecx is a smi, use times_half_pointer_size instead of
- // times_pointer_size
- __ mov(FieldOperand(edi,
- ecx,
- times_half_pointer_size,
- FixedArray::kHeaderSize), eax);
- } else {
- ASSERT(elements_kind == FAST_ELEMENTS);
- // Do the store and update the write barrier.
- // ecx is a smi, use times_half_pointer_size instead of
- // times_pointer_size
- __ lea(ecx, FieldOperand(edi,
- ecx,
- times_half_pointer_size,
- FixedArray::kHeaderSize));
- __ mov(Operand(ecx, 0), eax);
- // Make sure to preserve the value in register eax.
- __ mov(edx, eax);
- __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs);
- }
+ // Do the store and update the write barrier. Make sure to preserve
+ // the value in register eax.
+ __ mov(edx, Operand(eax));
+ __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax);
+ __ RecordWrite(edi, 0, edx, ecx);
// Done.
__ ret(0);
@@ -3968,11 +3884,6 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
Handle<Code> ic_force_generic =
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
-
- // Handle transition to other elements kinds without using the generic stub.
- __ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic_miss, RelocInfo::CODE_TARGET);
}
@@ -3985,7 +3896,8 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
- Label miss_force_generic, transition_elements_kind;
+ Label miss_force_generic, smi_value, is_nan, maybe_nan;
+ Label have_double_value, not_nan;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
@@ -4006,13 +3918,59 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
}
__ j(above_equal, &miss_force_generic);
- __ StoreNumberToDoubleElements(eax,
- edi,
- ecx,
- edx,
- xmm0,
- &transition_elements_kind,
- true);
+ __ JumpIfSmi(eax, &smi_value, Label::kNear);
+
+ __ CheckMap(eax,
+ masm->isolate()->factory()->heap_number_map(),
+ &miss_force_generic,
+ DONT_DO_SMI_CHECK);
+
+ // Double value, canonicalize NaN.
+ uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
+ __ cmp(FieldOperand(eax, offset), Immediate(kNaNOrInfinityLowerBoundUpper32));
+ __ j(greater_equal, &maybe_nan, Label::kNear);
+
+ __ bind(&not_nan);
+ ExternalReference canonical_nan_reference =
+ ExternalReference::address_of_canonical_non_hole_nan();
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope use_sse2(SSE2);
+ __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
+ __ bind(&have_double_value);
+ __ movdbl(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize),
+ xmm0);
+ __ ret(0);
+ } else {
+ __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+ __ bind(&have_double_value);
+ __ fstp_d(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize));
+ __ ret(0);
+ }
+
+ __ bind(&maybe_nan);
+ // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
+ // it's an Infinity, and the non-NaN code path applies.
+ __ j(greater, &is_nan, Label::kNear);
+ __ cmp(FieldOperand(eax, HeapNumber::kValueOffset), Immediate(0));
+ __ j(zero, &not_nan);
+ __ bind(&is_nan);
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope use_sse2(SSE2);
+ __ movdbl(xmm0, Operand::StaticVariable(canonical_nan_reference));
+ } else {
+ __ fld_d(Operand::StaticVariable(canonical_nan_reference));
+ }
+ __ jmp(&have_double_value, Label::kNear);
+
+ __ bind(&smi_value);
+ // Value is a smi. convert to a double and store.
+ // Preserve original value.
+ __ mov(edx, eax);
+ __ SmiUntag(edx);
+ __ push(edx);
+ __ fild_s(Operand(esp, 0));
+ __ pop(edx);
+ __ fstp_d(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize));
__ ret(0);
// Handle store cache miss, replacing the ic with the generic stub.
@@ -4020,11 +3978,6 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
Handle<Code> ic_force_generic =
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
-
- // Handle transition to other elements kinds without using the generic stub.
- __ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic_miss, RelocInfo::CODE_TARGET);
}