diff options
Diffstat (limited to 'deps/v8/src/ia32/stub-cache-ia32.cc')
-rw-r--r-- | deps/v8/src/ia32/stub-cache-ia32.cc | 401 |
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(¬_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, ¬_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); } |