| OLD | NEW | 
|    1 // Copyright 2014 the V8 project authors. All rights reserved. |    1 // Copyright 2012 the V8 project authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "src/v8.h" |    5 #include "src/v8.h" | 
|    6  |    6  | 
|    7 #if V8_TARGET_ARCH_IA32 |    7 #if V8_TARGET_ARCH_X87 | 
|    8  |    8  | 
|    9 #include "src/ic/call-optimization.h" |    9 #include "src/ic/call-optimization.h" | 
|   10 #include "src/ic/handler-compiler.h" |   10 #include "src/ic/handler-compiler.h" | 
|   11  |   11  | 
|   12 namespace v8 { |   12 namespace v8 { | 
|   13 namespace internal { |   13 namespace internal { | 
|   14  |   14  | 
|   15 #define __ ACCESS_MASM(masm) |   15 #define __ ACCESS_MASM(masm) | 
|   16  |   16  | 
|   17  |   17  | 
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  319  |  319  | 
|  320 static void CompileCallLoadPropertyWithInterceptor( |  320 static void CompileCallLoadPropertyWithInterceptor( | 
|  321     MacroAssembler* masm, Register receiver, Register holder, Register name, |  321     MacroAssembler* masm, Register receiver, Register holder, Register name, | 
|  322     Handle<JSObject> holder_obj, IC::UtilityId id) { |  322     Handle<JSObject> holder_obj, IC::UtilityId id) { | 
|  323   PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |  323   PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 
|  324   __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), |  324   __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), | 
|  325                            NamedLoadHandlerCompiler::kInterceptorArgsLength); |  325                            NamedLoadHandlerCompiler::kInterceptorArgsLength); | 
|  326 } |  326 } | 
|  327  |  327  | 
|  328  |  328  | 
|  329 static void StoreIC_PushArgs(MacroAssembler* masm) { |  | 
|  330   Register receiver = StoreIC::ReceiverRegister(); |  | 
|  331   Register name = StoreIC::NameRegister(); |  | 
|  332   Register value = StoreIC::ValueRegister(); |  | 
|  333  |  | 
|  334   DCHECK(!ebx.is(receiver) && !ebx.is(name) && !ebx.is(value)); |  | 
|  335  |  | 
|  336   __ pop(ebx); |  | 
|  337   __ push(receiver); |  | 
|  338   __ push(name); |  | 
|  339   __ push(value); |  | 
|  340   __ push(ebx); |  | 
|  341 } |  | 
|  342  |  | 
|  343  |  | 
|  344 void NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) { |  | 
|  345   // Return address is on the stack. |  | 
|  346   StoreIC_PushArgs(masm); |  | 
|  347  |  | 
|  348   // Do tail-call to runtime routine. |  | 
|  349   ExternalReference ref(IC_Utility(IC::kStoreIC_Slow), masm->isolate()); |  | 
|  350   __ TailCallExternalReference(ref, 3, 1); |  | 
|  351 } |  | 
|  352  |  | 
|  353  |  | 
|  354 void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { |  | 
|  355   // Return address is on the stack. |  | 
|  356   StoreIC_PushArgs(masm); |  | 
|  357  |  | 
|  358   // Do tail-call to runtime routine. |  | 
|  359   ExternalReference ref(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate()); |  | 
|  360   __ TailCallExternalReference(ref, 3, 1); |  | 
|  361 } |  | 
|  362  |  | 
|  363  |  | 
|  364 #undef __ |  329 #undef __ | 
|  365 #define __ ACCESS_MASM(masm()) |  330 #define __ ACCESS_MASM(masm()) | 
|  366  |  331  | 
|  367  |  332  | 
|  368 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, |  333 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, | 
|  369                                                     Handle<Name> name) { |  334                                                     Handle<Name> name) { | 
|  370   if (!label->is_unused()) { |  335   if (!label->is_unused()) { | 
|  371     __ bind(label); |  336     __ bind(label); | 
|  372     __ mov(this->name(), Immediate(name)); |  337     __ mov(this->name(), Immediate(name)); | 
|  373   } |  338   } | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  408         __ j(equal, &do_store, Label::kNear); |  373         __ j(equal, &do_store, Label::kNear); | 
|  409       } |  374       } | 
|  410       __ bind(&do_store); |  375       __ bind(&do_store); | 
|  411     } |  376     } | 
|  412   } else if (representation.IsDouble()) { |  377   } else if (representation.IsDouble()) { | 
|  413     Label do_store, heap_number; |  378     Label do_store, heap_number; | 
|  414     __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow, MUTABLE); |  379     __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow, MUTABLE); | 
|  415  |  380  | 
|  416     __ JumpIfNotSmi(value_reg, &heap_number); |  381     __ JumpIfNotSmi(value_reg, &heap_number); | 
|  417     __ SmiUntag(value_reg); |  382     __ SmiUntag(value_reg); | 
|  418     __ Cvtsi2sd(xmm0, value_reg); |  383     __ push(value_reg); | 
 |  384     __ fild_s(Operand(esp, 0)); | 
 |  385     __ pop(value_reg); | 
|  419     __ SmiTag(value_reg); |  386     __ SmiTag(value_reg); | 
|  420     __ jmp(&do_store); |  387     __ jmp(&do_store); | 
|  421  |  388  | 
|  422     __ bind(&heap_number); |  389     __ bind(&heap_number); | 
|  423     __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, |  390     __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, | 
|  424                 DONT_DO_SMI_CHECK); |  391                 DONT_DO_SMI_CHECK); | 
|  425     __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |  392     __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 
|  426  |  393  | 
|  427     __ bind(&do_store); |  394     __ bind(&do_store); | 
|  428     __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |  395     __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); | 
|  429   } |  396   } | 
|  430  |  397  | 
|  431   // Stub never generated for objects that require access checks. |  398   // Stub never generated for objects that require access checks. | 
|  432   DCHECK(!transition->is_access_check_needed()); |  399   DCHECK(!transition->is_access_check_needed()); | 
|  433  |  400  | 
|  434   // Perform map transition for the receiver if necessary. |  401   // Perform map transition for the receiver if necessary. | 
|  435   if (details.type() == FIELD && |  402   if (details.type() == FIELD && | 
|  436       Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |  403       Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 
|  437     // The properties must be extended before we can store the value. |  404     // The properties must be extended before we can store the value. | 
|  438     // We jump to a runtime call that extends the properties array. |  405     // We jump to a runtime call that extends the properties array. | 
|  439     __ pop(scratch1);  // Return address. |  406     __ pop(scratch1);  // Return address. | 
|  440     __ push(receiver_reg); |  407     __ push(receiver_reg); | 
|  441     __ push(Immediate(transition)); |  408     __ push(Immediate(transition)); | 
|  442     __ push(value_reg); |  409     __ push(value_reg); | 
|  443     __ push(scratch1); |  410     __ push(scratch1); | 
|  444     __ TailCallExternalReference( |  411     __ TailCallExternalReference( | 
|  445         ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |  412         ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 
|  446                           isolate()), |  413                           isolate()), | 
|  447         3, 1); |  414         3, 1); | 
|  448     return; |  415     return; | 
|  449   } |  416   } | 
|  450  |  417  | 
|  451   // Update the map of the object. |  418   // Update the map of the object. | 
|  452   __ mov(scratch1, Immediate(transition)); |  419   __ mov(scratch1, Immediate(transition)); | 
|  453   __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); |  420   __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); | 
|  454  |  421  | 
|  455   // Update the write barrier for the map field. |  422   // Update the write barrier for the map field. | 
|  456   __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2, |  423   __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2, | 
|  457                       kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |  424                       OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 
|  458  |  425  | 
|  459   if (details.type() == CONSTANT) { |  426   if (details.type() == CONSTANT) { | 
|  460     DCHECK(value_reg.is(eax)); |  427     DCHECK(value_reg.is(eax)); | 
|  461     __ ret(0); |  428     __ ret(0); | 
|  462     return; |  429     return; | 
|  463   } |  430   } | 
|  464  |  431  | 
|  465   int index = transition->instance_descriptors()->GetFieldIndex( |  432   int index = transition->instance_descriptors()->GetFieldIndex( | 
|  466       transition->LastAdded()); |  433       transition->LastAdded()); | 
|  467  |  434  | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|  481     } else { |  448     } else { | 
|  482       __ mov(FieldOperand(receiver_reg, offset), value_reg); |  449       __ mov(FieldOperand(receiver_reg, offset), value_reg); | 
|  483     } |  450     } | 
|  484  |  451  | 
|  485     if (!representation.IsSmi()) { |  452     if (!representation.IsSmi()) { | 
|  486       // Update the write barrier for the array address. |  453       // Update the write barrier for the array address. | 
|  487       if (!representation.IsDouble()) { |  454       if (!representation.IsDouble()) { | 
|  488         __ mov(storage_reg, value_reg); |  455         __ mov(storage_reg, value_reg); | 
|  489       } |  456       } | 
|  490       __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1, |  457       __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1, | 
|  491                           kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check); |  458                           EMIT_REMEMBERED_SET, smi_check); | 
|  492     } |  459     } | 
|  493   } else { |  460   } else { | 
|  494     // Write to the properties array. |  461     // Write to the properties array. | 
|  495     int offset = index * kPointerSize + FixedArray::kHeaderSize; |  462     int offset = index * kPointerSize + FixedArray::kHeaderSize; | 
|  496     // Get the properties array (optimistically). |  463     // Get the properties array (optimistically). | 
|  497     __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |  464     __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 
|  498     if (representation.IsDouble()) { |  465     if (representation.IsDouble()) { | 
|  499       __ mov(FieldOperand(scratch1, offset), storage_reg); |  466       __ mov(FieldOperand(scratch1, offset), storage_reg); | 
|  500     } else { |  467     } else { | 
|  501       __ mov(FieldOperand(scratch1, offset), value_reg); |  468       __ mov(FieldOperand(scratch1, offset), value_reg); | 
|  502     } |  469     } | 
|  503  |  470  | 
|  504     if (!representation.IsSmi()) { |  471     if (!representation.IsSmi()) { | 
|  505       // Update the write barrier for the array address. |  472       // Update the write barrier for the array address. | 
|  506       if (!representation.IsDouble()) { |  473       if (!representation.IsDouble()) { | 
|  507         __ mov(storage_reg, value_reg); |  474         __ mov(storage_reg, value_reg); | 
|  508       } |  475       } | 
|  509       __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg, |  476       __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg, | 
|  510                           kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check); |  477                           EMIT_REMEMBERED_SET, smi_check); | 
|  511     } |  478     } | 
|  512   } |  479   } | 
|  513  |  480  | 
|  514   // Return the value (register eax). |  481   // Return the value (register eax). | 
|  515   DCHECK(value_reg.is(eax)); |  482   DCHECK(value_reg.is(eax)); | 
|  516   __ ret(0); |  483   __ ret(0); | 
|  517 } |  484 } | 
|  518  |  485  | 
|  519  |  486  | 
|  520 void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup, |  487 void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup, | 
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  887  |  854  | 
|  888   // Return the generated code. |  855   // Return the generated code. | 
|  889   return GetCode(kind(), Code::NORMAL, name); |  856   return GetCode(kind(), Code::NORMAL, name); | 
|  890 } |  857 } | 
|  891  |  858  | 
|  892  |  859  | 
|  893 #undef __ |  860 #undef __ | 
|  894 } |  861 } | 
|  895 }  // namespace v8::internal |  862 }  // namespace v8::internal | 
|  896  |  863  | 
|  897 #endif  // V8_TARGET_ARCH_IA32 |  864 #endif  // V8_TARGET_ARCH_X87 | 
| OLD | NEW |