| OLD | NEW | 
|---|
| 1 // Copyright 2012 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_X87 | 7 #if V8_TARGET_ARCH_X87 | 
| 8 | 8 | 
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" | 
| 10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" | 
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 110     // Pop at miss. | 110     // Pop at miss. | 
| 111     __ bind(&miss); | 111     __ bind(&miss); | 
| 112     __ pop(offset); | 112     __ pop(offset); | 
| 113   } | 113   } | 
| 114 } | 114 } | 
| 115 | 115 | 
| 116 | 116 | 
| 117 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 117 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 
| 118     MacroAssembler* masm, Label* miss_label, Register receiver, | 118     MacroAssembler* masm, Label* miss_label, Register receiver, | 
| 119     Handle<Name> name, Register scratch0, Register scratch1) { | 119     Handle<Name> name, Register scratch0, Register scratch1) { | 
| 120   ASSERT(name->IsUniqueName()); | 120   DCHECK(name->IsUniqueName()); | 
| 121   ASSERT(!receiver.is(scratch0)); | 121   DCHECK(!receiver.is(scratch0)); | 
| 122   Counters* counters = masm->isolate()->counters(); | 122   Counters* counters = masm->isolate()->counters(); | 
| 123   __ IncrementCounter(counters->negative_lookups(), 1); | 123   __ IncrementCounter(counters->negative_lookups(), 1); | 
| 124   __ IncrementCounter(counters->negative_lookups_miss(), 1); | 124   __ IncrementCounter(counters->negative_lookups_miss(), 1); | 
| 125 | 125 | 
| 126   __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); | 126   __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); | 
| 127 | 127 | 
| 128   const int kInterceptorOrAccessCheckNeededMask = | 128   const int kInterceptorOrAccessCheckNeededMask = | 
| 129       (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 129       (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 
| 130 | 130 | 
| 131   // Bail out if the receiver has a named interceptor or requires access checks. | 131   // Bail out if the receiver has a named interceptor or requires access checks. | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 163                               Register receiver, | 163                               Register receiver, | 
| 164                               Register name, | 164                               Register name, | 
| 165                               Register scratch, | 165                               Register scratch, | 
| 166                               Register extra, | 166                               Register extra, | 
| 167                               Register extra2, | 167                               Register extra2, | 
| 168                               Register extra3) { | 168                               Register extra3) { | 
| 169   Label miss; | 169   Label miss; | 
| 170 | 170 | 
| 171   // Assert that code is valid.  The multiplying code relies on the entry size | 171   // Assert that code is valid.  The multiplying code relies on the entry size | 
| 172   // being 12. | 172   // being 12. | 
| 173   ASSERT(sizeof(Entry) == 12); | 173   DCHECK(sizeof(Entry) == 12); | 
| 174 | 174 | 
| 175   // Assert the flags do not name a specific type. | 175   // Assert the flags do not name a specific type. | 
| 176   ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 176   DCHECK(Code::ExtractTypeFromFlags(flags) == 0); | 
| 177 | 177 | 
| 178   // Assert that there are no register conflicts. | 178   // Assert that there are no register conflicts. | 
| 179   ASSERT(!scratch.is(receiver)); | 179   DCHECK(!scratch.is(receiver)); | 
| 180   ASSERT(!scratch.is(name)); | 180   DCHECK(!scratch.is(name)); | 
| 181   ASSERT(!extra.is(receiver)); | 181   DCHECK(!extra.is(receiver)); | 
| 182   ASSERT(!extra.is(name)); | 182   DCHECK(!extra.is(name)); | 
| 183   ASSERT(!extra.is(scratch)); | 183   DCHECK(!extra.is(scratch)); | 
| 184 | 184 | 
| 185   // Assert scratch and extra registers are valid, and extra2/3 are unused. | 185   // Assert scratch and extra registers are valid, and extra2/3 are unused. | 
| 186   ASSERT(!scratch.is(no_reg)); | 186   DCHECK(!scratch.is(no_reg)); | 
| 187   ASSERT(extra2.is(no_reg)); | 187   DCHECK(extra2.is(no_reg)); | 
| 188   ASSERT(extra3.is(no_reg)); | 188   DCHECK(extra3.is(no_reg)); | 
| 189 | 189 | 
| 190   Register offset = scratch; | 190   Register offset = scratch; | 
| 191   scratch = no_reg; | 191   scratch = no_reg; | 
| 192 | 192 | 
| 193   Counters* counters = masm->isolate()->counters(); | 193   Counters* counters = masm->isolate()->counters(); | 
| 194   __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); | 194   __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); | 
| 195 | 195 | 
| 196   // Check that the receiver isn't a smi. | 196   // Check that the receiver isn't a smi. | 
| 197   __ JumpIfSmi(receiver, &miss); | 197   __ JumpIfSmi(receiver, &miss); | 
| 198 | 198 | 
| 199   // Get the map of the receiver and compute the hash. | 199   // Get the map of the receiver and compute the hash. | 
| 200   __ mov(offset, FieldOperand(name, Name::kHashFieldOffset)); | 200   __ mov(offset, FieldOperand(name, Name::kHashFieldOffset)); | 
| 201   __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset)); | 201   __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset)); | 
| 202   __ xor_(offset, flags); | 202   __ xor_(offset, flags); | 
| 203   // We mask out the last two bits because they are not part of the hash and | 203   // We mask out the last two bits because they are not part of the hash and | 
| 204   // they are always 01 for maps.  Also in the two 'and' instructions below. | 204   // they are always 01 for maps.  Also in the two 'and' instructions below. | 
| 205   __ and_(offset, (kPrimaryTableSize - 1) << kCacheIndexShift); | 205   __ and_(offset, (kPrimaryTableSize - 1) << kCacheIndexShift); | 
| 206   // ProbeTable expects the offset to be pointer scaled, which it is, because | 206   // ProbeTable expects the offset to be pointer scaled, which it is, because | 
| 207   // the heap object tag size is 2 and the pointer size log 2 is also 2. | 207   // the heap object tag size is 2 and the pointer size log 2 is also 2. | 
| 208   ASSERT(kCacheIndexShift == kPointerSizeLog2); | 208   DCHECK(kCacheIndexShift == kPointerSizeLog2); | 
| 209 | 209 | 
| 210   // Probe the primary table. | 210   // Probe the primary table. | 
| 211   ProbeTable(isolate(), masm, flags, kPrimary, name, receiver, offset, extra); | 211   ProbeTable(isolate(), masm, flags, kPrimary, name, receiver, offset, extra); | 
| 212 | 212 | 
| 213   // Primary miss: Compute hash for secondary probe. | 213   // Primary miss: Compute hash for secondary probe. | 
| 214   __ mov(offset, FieldOperand(name, Name::kHashFieldOffset)); | 214   __ mov(offset, FieldOperand(name, Name::kHashFieldOffset)); | 
| 215   __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset)); | 215   __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset)); | 
| 216   __ xor_(offset, flags); | 216   __ xor_(offset, flags); | 
| 217   __ and_(offset, (kPrimaryTableSize - 1) << kCacheIndexShift); | 217   __ and_(offset, (kPrimaryTableSize - 1) << kCacheIndexShift); | 
| 218   __ sub(offset, name); | 218   __ sub(offset, name); | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 264                                      Register holder, | 264                                      Register holder, | 
| 265                                      Register name, | 265                                      Register name, | 
| 266                                      Handle<JSObject> holder_obj) { | 266                                      Handle<JSObject> holder_obj) { | 
| 267   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 267   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 
| 268   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); | 268   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); | 
| 269   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); | 269   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); | 
| 270   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); | 270   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); | 
| 271   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); | 271   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); | 
| 272   __ push(name); | 272   __ push(name); | 
| 273   Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 273   Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 
| 274   ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 274   DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 
| 275   Register scratch = name; | 275   Register scratch = name; | 
| 276   __ mov(scratch, Immediate(interceptor)); | 276   __ mov(scratch, Immediate(interceptor)); | 
| 277   __ push(scratch); | 277   __ push(scratch); | 
| 278   __ push(receiver); | 278   __ push(receiver); | 
| 279   __ push(holder); | 279   __ push(holder); | 
| 280 } | 280 } | 
| 281 | 281 | 
| 282 | 282 | 
| 283 static void CompileCallLoadPropertyWithInterceptor( | 283 static void CompileCallLoadPropertyWithInterceptor( | 
| 284     MacroAssembler* masm, | 284     MacroAssembler* masm, | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 301     MacroAssembler* masm, const CallOptimization& optimization, | 301     MacroAssembler* masm, const CallOptimization& optimization, | 
| 302     Handle<Map> receiver_map, Register receiver, Register scratch_in, | 302     Handle<Map> receiver_map, Register receiver, Register scratch_in, | 
| 303     bool is_store, int argc, Register* values) { | 303     bool is_store, int argc, Register* values) { | 
| 304   // Copy return value. | 304   // Copy return value. | 
| 305   __ pop(scratch_in); | 305   __ pop(scratch_in); | 
| 306   // receiver | 306   // receiver | 
| 307   __ push(receiver); | 307   __ push(receiver); | 
| 308   // Write the arguments to stack frame. | 308   // Write the arguments to stack frame. | 
| 309   for (int i = 0; i < argc; i++) { | 309   for (int i = 0; i < argc; i++) { | 
| 310     Register arg = values[argc-1-i]; | 310     Register arg = values[argc-1-i]; | 
| 311     ASSERT(!receiver.is(arg)); | 311     DCHECK(!receiver.is(arg)); | 
| 312     ASSERT(!scratch_in.is(arg)); | 312     DCHECK(!scratch_in.is(arg)); | 
| 313     __ push(arg); | 313     __ push(arg); | 
| 314   } | 314   } | 
| 315   __ push(scratch_in); | 315   __ push(scratch_in); | 
| 316   // Stack now matches JSFunction abi. | 316   // Stack now matches JSFunction abi. | 
| 317   ASSERT(optimization.is_simple_api_call()); | 317   DCHECK(optimization.is_simple_api_call()); | 
| 318 | 318 | 
| 319   // Abi for CallApiFunctionStub. | 319   // Abi for CallApiFunctionStub. | 
| 320   Register callee = eax; | 320   Register callee = eax; | 
| 321   Register call_data = ebx; | 321   Register call_data = ebx; | 
| 322   Register holder = ecx; | 322   Register holder = ecx; | 
| 323   Register api_function_address = edx; | 323   Register api_function_address = edx; | 
| 324   Register scratch = edi;  // scratch_in is no longer valid. | 324   Register scratch = edi;  // scratch_in is no longer valid. | 
| 325 | 325 | 
| 326   // Put holder in place. | 326   // Put holder in place. | 
| 327   CallOptimization::HolderLookup holder_lookup; | 327   CallOptimization::HolderLookup holder_lookup; | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 381 | 381 | 
| 382 | 382 | 
| 383 // Generate code to check that a global property cell is empty. Create | 383 // Generate code to check that a global property cell is empty. Create | 
| 384 // the property cell at compilation time if no cell exists for the | 384 // the property cell at compilation time if no cell exists for the | 
| 385 // property. | 385 // property. | 
| 386 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 386 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 
| 387     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 387     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 
| 388     Register scratch, Label* miss) { | 388     Register scratch, Label* miss) { | 
| 389   Handle<PropertyCell> cell = | 389   Handle<PropertyCell> cell = | 
| 390       JSGlobalObject::EnsurePropertyCell(global, name); | 390       JSGlobalObject::EnsurePropertyCell(global, name); | 
| 391   ASSERT(cell->value()->IsTheHole()); | 391   DCHECK(cell->value()->IsTheHole()); | 
| 392   Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); | 392   Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); | 
| 393   if (masm->serializer_enabled()) { | 393   if (masm->serializer_enabled()) { | 
| 394     __ mov(scratch, Immediate(cell)); | 394     __ mov(scratch, Immediate(cell)); | 
| 395     __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 395     __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 
| 396            Immediate(the_hole)); | 396            Immediate(the_hole)); | 
| 397   } else { | 397   } else { | 
| 398     __ cmp(Operand::ForCell(cell), Immediate(the_hole)); | 398     __ cmp(Operand::ForCell(cell), Immediate(the_hole)); | 
| 399   } | 399   } | 
| 400   __ j(not_equal, miss); | 400   __ j(not_equal, miss); | 
| 401 } | 401 } | 
| 402 | 402 | 
| 403 | 403 | 
| 404 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 404 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 
| 405 // store is successful. | 405 // store is successful. | 
| 406 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 406 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 
| 407     MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, | 407     MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, | 
| 408     Handle<Name> name, Register receiver_reg, Register storage_reg, | 408     Handle<Name> name, Register receiver_reg, Register storage_reg, | 
| 409     Register value_reg, Register scratch1, Register scratch2, Register unused, | 409     Register value_reg, Register scratch1, Register scratch2, Register unused, | 
| 410     Label* miss_label, Label* slow) { | 410     Label* miss_label, Label* slow) { | 
| 411   int descriptor = transition->LastAdded(); | 411   int descriptor = transition->LastAdded(); | 
| 412   DescriptorArray* descriptors = transition->instance_descriptors(); | 412   DescriptorArray* descriptors = transition->instance_descriptors(); | 
| 413   PropertyDetails details = descriptors->GetDetails(descriptor); | 413   PropertyDetails details = descriptors->GetDetails(descriptor); | 
| 414   Representation representation = details.representation(); | 414   Representation representation = details.representation(); | 
| 415   ASSERT(!representation.IsNone()); | 415   DCHECK(!representation.IsNone()); | 
| 416 | 416 | 
| 417   if (details.type() == CONSTANT) { | 417   if (details.type() == CONSTANT) { | 
| 418     Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 418     Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 
| 419     __ CmpObject(value_reg, constant); | 419     __ CmpObject(value_reg, constant); | 
| 420     __ j(not_equal, miss_label); | 420     __ j(not_equal, miss_label); | 
| 421   } else if (representation.IsSmi()) { | 421   } else if (representation.IsSmi()) { | 
| 422       __ JumpIfNotSmi(value_reg, miss_label); | 422       __ JumpIfNotSmi(value_reg, miss_label); | 
| 423   } else if (representation.IsHeapObject()) { | 423   } else if (representation.IsHeapObject()) { | 
| 424     __ JumpIfSmi(value_reg, miss_label); | 424     __ JumpIfSmi(value_reg, miss_label); | 
| 425     HeapType* field_type = descriptors->GetFieldType(descriptor); | 425     HeapType* field_type = descriptors->GetFieldType(descriptor); | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 452     __ bind(&heap_number); | 452     __ bind(&heap_number); | 
| 453     __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 453     __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 
| 454                 miss_label, DONT_DO_SMI_CHECK); | 454                 miss_label, DONT_DO_SMI_CHECK); | 
| 455     __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 455     __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 
| 456 | 456 | 
| 457     __ bind(&do_store); | 457     __ bind(&do_store); | 
| 458     __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); | 458     __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); | 
| 459   } | 459   } | 
| 460 | 460 | 
| 461   // Stub never generated for objects that require access checks. | 461   // Stub never generated for objects that require access checks. | 
| 462   ASSERT(!transition->is_access_check_needed()); | 462   DCHECK(!transition->is_access_check_needed()); | 
| 463 | 463 | 
| 464   // Perform map transition for the receiver if necessary. | 464   // Perform map transition for the receiver if necessary. | 
| 465   if (details.type() == FIELD && | 465   if (details.type() == FIELD && | 
| 466       Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 466       Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 
| 467     // The properties must be extended before we can store the value. | 467     // The properties must be extended before we can store the value. | 
| 468     // We jump to a runtime call that extends the properties array. | 468     // We jump to a runtime call that extends the properties array. | 
| 469     __ pop(scratch1);  // Return address. | 469     __ pop(scratch1);  // Return address. | 
| 470     __ push(receiver_reg); | 470     __ push(receiver_reg); | 
| 471     __ push(Immediate(transition)); | 471     __ push(Immediate(transition)); | 
| 472     __ push(value_reg); | 472     __ push(value_reg); | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 485 | 485 | 
| 486   // Update the write barrier for the map field. | 486   // Update the write barrier for the map field. | 
| 487   __ RecordWriteField(receiver_reg, | 487   __ RecordWriteField(receiver_reg, | 
| 488                       HeapObject::kMapOffset, | 488                       HeapObject::kMapOffset, | 
| 489                       scratch1, | 489                       scratch1, | 
| 490                       scratch2, | 490                       scratch2, | 
| 491                       OMIT_REMEMBERED_SET, | 491                       OMIT_REMEMBERED_SET, | 
| 492                       OMIT_SMI_CHECK); | 492                       OMIT_SMI_CHECK); | 
| 493 | 493 | 
| 494   if (details.type() == CONSTANT) { | 494   if (details.type() == CONSTANT) { | 
| 495     ASSERT(value_reg.is(eax)); | 495     DCHECK(value_reg.is(eax)); | 
| 496     __ ret(0); | 496     __ ret(0); | 
| 497     return; | 497     return; | 
| 498   } | 498   } | 
| 499 | 499 | 
| 500   int index = transition->instance_descriptors()->GetFieldIndex( | 500   int index = transition->instance_descriptors()->GetFieldIndex( | 
| 501       transition->LastAdded()); | 501       transition->LastAdded()); | 
| 502 | 502 | 
| 503   // Adjust for the number of properties stored in the object. Even in the | 503   // Adjust for the number of properties stored in the object. Even in the | 
| 504   // face of a transition we can use the old map here because the size of the | 504   // face of a transition we can use the old map here because the size of the | 
| 505   // object and the number of in-object properties is not going to change. | 505   // object and the number of in-object properties is not going to change. | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 548       __ RecordWriteField(scratch1, | 548       __ RecordWriteField(scratch1, | 
| 549                           offset, | 549                           offset, | 
| 550                           storage_reg, | 550                           storage_reg, | 
| 551                           receiver_reg, | 551                           receiver_reg, | 
| 552                           EMIT_REMEMBERED_SET, | 552                           EMIT_REMEMBERED_SET, | 
| 553                           smi_check); | 553                           smi_check); | 
| 554     } | 554     } | 
| 555   } | 555   } | 
| 556 | 556 | 
| 557   // Return the value (register eax). | 557   // Return the value (register eax). | 
| 558   ASSERT(value_reg.is(eax)); | 558   DCHECK(value_reg.is(eax)); | 
| 559   __ ret(0); | 559   __ ret(0); | 
| 560 } | 560 } | 
| 561 | 561 | 
| 562 | 562 | 
| 563 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 563 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 
| 564 // but may be destroyed if store is successful. | 564 // but may be destroyed if store is successful. | 
| 565 void NamedStoreHandlerCompiler::GenerateStoreField( | 565 void NamedStoreHandlerCompiler::GenerateStoreField( | 
| 566     MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 566     MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 
| 567     Register receiver_reg, Register name_reg, Register value_reg, | 567     Register receiver_reg, Register name_reg, Register value_reg, | 
| 568     Register scratch1, Register scratch2, Label* miss_label) { | 568     Register scratch1, Register scratch2, Label* miss_label) { | 
| 569   // Stub never generated for non-global objects that require access | 569   // Stub never generated for non-global objects that require access | 
| 570   // checks. | 570   // checks. | 
| 571   ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 571   DCHECK(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 
| 572 | 572 | 
| 573   FieldIndex index = lookup->GetFieldIndex(); | 573   FieldIndex index = lookup->GetFieldIndex(); | 
| 574 | 574 | 
| 575   Representation representation = lookup->representation(); | 575   Representation representation = lookup->representation(); | 
| 576   ASSERT(!representation.IsNone()); | 576   DCHECK(!representation.IsNone()); | 
| 577   if (representation.IsSmi()) { | 577   if (representation.IsSmi()) { | 
| 578     __ JumpIfNotSmi(value_reg, miss_label); | 578     __ JumpIfNotSmi(value_reg, miss_label); | 
| 579   } else if (representation.IsHeapObject()) { | 579   } else if (representation.IsHeapObject()) { | 
| 580     __ JumpIfSmi(value_reg, miss_label); | 580     __ JumpIfSmi(value_reg, miss_label); | 
| 581     HeapType* field_type = lookup->GetFieldType(); | 581     HeapType* field_type = lookup->GetFieldType(); | 
| 582     HeapType::Iterator<Map> it = field_type->Classes(); | 582     HeapType::Iterator<Map> it = field_type->Classes(); | 
| 583     if (!it.Done()) { | 583     if (!it.Done()) { | 
| 584       Label do_store; | 584       Label do_store; | 
| 585       while (true) { | 585       while (true) { | 
| 586         __ CompareMap(value_reg, it.Current()); | 586         __ CompareMap(value_reg, it.Current()); | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 611     __ pop(value_reg); | 611     __ pop(value_reg); | 
| 612     __ SmiTag(value_reg); | 612     __ SmiTag(value_reg); | 
| 613     __ jmp(&do_store); | 613     __ jmp(&do_store); | 
| 614     __ bind(&heap_number); | 614     __ bind(&heap_number); | 
| 615     __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 615     __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 
| 616                 miss_label, DONT_DO_SMI_CHECK); | 616                 miss_label, DONT_DO_SMI_CHECK); | 
| 617     __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 617     __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 
| 618     __ bind(&do_store); | 618     __ bind(&do_store); | 
| 619     __ fstp_d(FieldOperand(scratch1, HeapNumber::kValueOffset)); | 619     __ fstp_d(FieldOperand(scratch1, HeapNumber::kValueOffset)); | 
| 620     // Return the value (register eax). | 620     // Return the value (register eax). | 
| 621     ASSERT(value_reg.is(eax)); | 621     DCHECK(value_reg.is(eax)); | 
| 622     __ ret(0); | 622     __ ret(0); | 
| 623     return; | 623     return; | 
| 624   } | 624   } | 
| 625 | 625 | 
| 626   ASSERT(!representation.IsDouble()); | 626   DCHECK(!representation.IsDouble()); | 
| 627   // TODO(verwaest): Share this code as a code stub. | 627   // TODO(verwaest): Share this code as a code stub. | 
| 628   SmiCheck smi_check = representation.IsTagged() | 628   SmiCheck smi_check = representation.IsTagged() | 
| 629       ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 629       ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 
| 630   if (index.is_inobject()) { | 630   if (index.is_inobject()) { | 
| 631     // Set the property straight into the object. | 631     // Set the property straight into the object. | 
| 632     __ mov(FieldOperand(receiver_reg, index.offset()), value_reg); | 632     __ mov(FieldOperand(receiver_reg, index.offset()), value_reg); | 
| 633 | 633 | 
| 634     if (!representation.IsSmi()) { | 634     if (!representation.IsSmi()) { | 
| 635       // Update the write barrier for the array address. | 635       // Update the write barrier for the array address. | 
| 636       // Pass the value being stored in the now unused name_reg. | 636       // Pass the value being stored in the now unused name_reg. | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 655       __ RecordWriteField(scratch1, | 655       __ RecordWriteField(scratch1, | 
| 656                           index.offset(), | 656                           index.offset(), | 
| 657                           name_reg, | 657                           name_reg, | 
| 658                           receiver_reg, | 658                           receiver_reg, | 
| 659                           EMIT_REMEMBERED_SET, | 659                           EMIT_REMEMBERED_SET, | 
| 660                           smi_check); | 660                           smi_check); | 
| 661     } | 661     } | 
| 662   } | 662   } | 
| 663 | 663 | 
| 664   // Return the value (register eax). | 664   // Return the value (register eax). | 
| 665   ASSERT(value_reg.is(eax)); | 665   DCHECK(value_reg.is(eax)); | 
| 666   __ ret(0); | 666   __ ret(0); | 
| 667 } | 667 } | 
| 668 | 668 | 
| 669 | 669 | 
| 670 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, | 670 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, | 
| 671                                               Handle<Code> code) { | 671                                               Handle<Code> code) { | 
| 672   __ jmp(code, RelocInfo::CODE_TARGET); | 672   __ jmp(code, RelocInfo::CODE_TARGET); | 
| 673 } | 673 } | 
| 674 | 674 | 
| 675 | 675 | 
| 676 #undef __ | 676 #undef __ | 
| 677 #define __ ACCESS_MASM(masm()) | 677 #define __ ACCESS_MASM(masm()) | 
| 678 | 678 | 
| 679 | 679 | 
| 680 Register PropertyHandlerCompiler::CheckPrototypes( | 680 Register PropertyHandlerCompiler::CheckPrototypes( | 
| 681     Register object_reg, Register holder_reg, Register scratch1, | 681     Register object_reg, Register holder_reg, Register scratch1, | 
| 682     Register scratch2, Handle<Name> name, Label* miss, | 682     Register scratch2, Handle<Name> name, Label* miss, | 
| 683     PrototypeCheckType check) { | 683     PrototypeCheckType check) { | 
| 684   Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 684   Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 
| 685 | 685 | 
| 686   // Make sure there's no overlap between holder and object registers. | 686   // Make sure there's no overlap between holder and object registers. | 
| 687   ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 687   DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 
| 688   ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 688   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 
| 689          && !scratch2.is(scratch1)); | 689          && !scratch2.is(scratch1)); | 
| 690 | 690 | 
| 691   // Keep track of the current object in register reg. | 691   // Keep track of the current object in register reg. | 
| 692   Register reg = object_reg; | 692   Register reg = object_reg; | 
| 693   int depth = 0; | 693   int depth = 0; | 
| 694 | 694 | 
| 695   Handle<JSObject> current = Handle<JSObject>::null(); | 695   Handle<JSObject> current = Handle<JSObject>::null(); | 
| 696   if (type()->IsConstant()) | 696   if (type()->IsConstant()) | 
| 697     current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 697     current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 
| 698   Handle<JSObject> prototype = Handle<JSObject>::null(); | 698   Handle<JSObject> prototype = Handle<JSObject>::null(); | 
| 699   Handle<Map> current_map = receiver_map; | 699   Handle<Map> current_map = receiver_map; | 
| 700   Handle<Map> holder_map(holder()->map()); | 700   Handle<Map> holder_map(holder()->map()); | 
| 701   // Traverse the prototype chain and check the maps in the prototype chain for | 701   // Traverse the prototype chain and check the maps in the prototype chain for | 
| 702   // fast and global objects or do negative lookup for normal objects. | 702   // fast and global objects or do negative lookup for normal objects. | 
| 703   while (!current_map.is_identical_to(holder_map)) { | 703   while (!current_map.is_identical_to(holder_map)) { | 
| 704     ++depth; | 704     ++depth; | 
| 705 | 705 | 
| 706     // Only global objects and objects that do not require access | 706     // Only global objects and objects that do not require access | 
| 707     // checks are allowed in stubs. | 707     // checks are allowed in stubs. | 
| 708     ASSERT(current_map->IsJSGlobalProxyMap() || | 708     DCHECK(current_map->IsJSGlobalProxyMap() || | 
| 709            !current_map->is_access_check_needed()); | 709            !current_map->is_access_check_needed()); | 
| 710 | 710 | 
| 711     prototype = handle(JSObject::cast(current_map->prototype())); | 711     prototype = handle(JSObject::cast(current_map->prototype())); | 
| 712     if (current_map->is_dictionary_map() && | 712     if (current_map->is_dictionary_map() && | 
| 713         !current_map->IsJSGlobalObjectMap() && | 713         !current_map->IsJSGlobalObjectMap() && | 
| 714         !current_map->IsJSGlobalProxyMap()) { | 714         !current_map->IsJSGlobalProxyMap()) { | 
| 715       if (!name->IsUniqueName()) { | 715       if (!name->IsUniqueName()) { | 
| 716         ASSERT(name->IsString()); | 716         DCHECK(name->IsString()); | 
| 717         name = factory()->InternalizeString(Handle<String>::cast(name)); | 717         name = factory()->InternalizeString(Handle<String>::cast(name)); | 
| 718       } | 718       } | 
| 719       ASSERT(current.is_null() || | 719       DCHECK(current.is_null() || | 
| 720              current->property_dictionary()->FindEntry(name) == | 720              current->property_dictionary()->FindEntry(name) == | 
| 721              NameDictionary::kNotFound); | 721              NameDictionary::kNotFound); | 
| 722 | 722 | 
| 723       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 723       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 
| 724                                        scratch1, scratch2); | 724                                        scratch1, scratch2); | 
| 725 | 725 | 
| 726       __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 726       __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 
| 727       reg = holder_reg;  // From now on the object will be in holder_reg. | 727       reg = holder_reg;  // From now on the object will be in holder_reg. | 
| 728       __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 728       __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 
| 729     } else { | 729     } else { | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 769 | 769 | 
| 770   // Log the check depth. | 770   // Log the check depth. | 
| 771   LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 771   LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 
| 772 | 772 | 
| 773   if (depth != 0 || check == CHECK_ALL_MAPS) { | 773   if (depth != 0 || check == CHECK_ALL_MAPS) { | 
| 774     // Check the holder map. | 774     // Check the holder map. | 
| 775     __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); | 775     __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); | 
| 776   } | 776   } | 
| 777 | 777 | 
| 778   // Perform security check for access to the global object. | 778   // Perform security check for access to the global object. | 
| 779   ASSERT(current_map->IsJSGlobalProxyMap() || | 779   DCHECK(current_map->IsJSGlobalProxyMap() || | 
| 780          !current_map->is_access_check_needed()); | 780          !current_map->is_access_check_needed()); | 
| 781   if (current_map->IsJSGlobalProxyMap()) { | 781   if (current_map->IsJSGlobalProxyMap()) { | 
| 782     __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 782     __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 
| 783   } | 783   } | 
| 784 | 784 | 
| 785   // Return the register containing the holder. | 785   // Return the register containing the holder. | 
| 786   return reg; | 786   return reg; | 
| 787 } | 787 } | 
| 788 | 788 | 
| 789 | 789 | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 810 | 810 | 
| 811 | 811 | 
| 812 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 812 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 
| 813                                                     Handle<Name> name, | 813                                                     Handle<Name> name, | 
| 814                                                     Handle<Object> callback) { | 814                                                     Handle<Object> callback) { | 
| 815   Label miss; | 815   Label miss; | 
| 816 | 816 | 
| 817   Register reg = FrontendHeader(object_reg, name, &miss); | 817   Register reg = FrontendHeader(object_reg, name, &miss); | 
| 818 | 818 | 
| 819   if (!holder()->HasFastProperties()) { | 819   if (!holder()->HasFastProperties()) { | 
| 820     ASSERT(!holder()->IsGlobalObject()); | 820     DCHECK(!holder()->IsGlobalObject()); | 
| 821     ASSERT(!reg.is(scratch2())); | 821     DCHECK(!reg.is(scratch2())); | 
| 822     ASSERT(!reg.is(scratch3())); | 822     DCHECK(!reg.is(scratch3())); | 
| 823     Register dictionary = scratch1(); | 823     Register dictionary = scratch1(); | 
| 824     bool must_preserve_dictionary_reg = reg.is(dictionary); | 824     bool must_preserve_dictionary_reg = reg.is(dictionary); | 
| 825 | 825 | 
| 826     // Load the properties dictionary. | 826     // Load the properties dictionary. | 
| 827     if (must_preserve_dictionary_reg) { | 827     if (must_preserve_dictionary_reg) { | 
| 828       __ push(dictionary); | 828       __ push(dictionary); | 
| 829     } | 829     } | 
| 830     __ mov(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 830     __ mov(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 
| 831 | 831 | 
| 832     // Probe the dictionary. | 832     // Probe the dictionary. | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 870     Register reg, FieldIndex field, Representation representation) { | 870     Register reg, FieldIndex field, Representation representation) { | 
| 871   if (!reg.is(receiver())) __ mov(receiver(), reg); | 871   if (!reg.is(receiver())) __ mov(receiver(), reg); | 
| 872   LoadFieldStub stub(isolate(), field); | 872   LoadFieldStub stub(isolate(), field); | 
| 873   GenerateTailCall(masm(), stub.GetCode()); | 873   GenerateTailCall(masm(), stub.GetCode()); | 
| 874 } | 874 } | 
| 875 | 875 | 
| 876 | 876 | 
| 877 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 877 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 
| 878     Register reg, Handle<ExecutableAccessorInfo> callback) { | 878     Register reg, Handle<ExecutableAccessorInfo> callback) { | 
| 879   // Insert additional parameters into the stack frame above return address. | 879   // Insert additional parameters into the stack frame above return address. | 
| 880   ASSERT(!scratch3().is(reg)); | 880   DCHECK(!scratch3().is(reg)); | 
| 881   __ pop(scratch3());  // Get return address to place it below. | 881   __ pop(scratch3());  // Get return address to place it below. | 
| 882 | 882 | 
| 883   STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 883   STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 
| 884   STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 884   STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 
| 885   STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 885   STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 
| 886   STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 886   STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 
| 887   STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 887   STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 
| 888   STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 888   STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 
| 889   __ push(receiver());  // receiver | 889   __ push(receiver());  // receiver | 
| 890   // Push data from ExecutableAccessorInfo. | 890   // Push data from ExecutableAccessorInfo. | 
| 891   if (isolate()->heap()->InNewSpace(callback->data())) { | 891   if (isolate()->heap()->InNewSpace(callback->data())) { | 
| 892     ASSERT(!scratch2().is(reg)); | 892     DCHECK(!scratch2().is(reg)); | 
| 893     __ mov(scratch2(), Immediate(callback)); | 893     __ mov(scratch2(), Immediate(callback)); | 
| 894     __ push(FieldOperand(scratch2(), ExecutableAccessorInfo::kDataOffset)); | 894     __ push(FieldOperand(scratch2(), ExecutableAccessorInfo::kDataOffset)); | 
| 895   } else { | 895   } else { | 
| 896     __ push(Immediate(Handle<Object>(callback->data(), isolate()))); | 896     __ push(Immediate(Handle<Object>(callback->data(), isolate()))); | 
| 897   } | 897   } | 
| 898   __ push(Immediate(isolate()->factory()->undefined_value()));  // ReturnValue | 898   __ push(Immediate(isolate()->factory()->undefined_value()));  // ReturnValue | 
| 899   // ReturnValue default value | 899   // ReturnValue default value | 
| 900   __ push(Immediate(isolate()->factory()->undefined_value())); | 900   __ push(Immediate(isolate()->factory()->undefined_value())); | 
| 901   __ push(Immediate(reinterpret_cast<int>(isolate()))); | 901   __ push(Immediate(reinterpret_cast<int>(isolate()))); | 
| 902   __ push(reg);  // holder | 902   __ push(reg);  // holder | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 922 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 922 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 
| 923   // Return the constant value. | 923   // Return the constant value. | 
| 924   __ LoadObject(eax, value); | 924   __ LoadObject(eax, value); | 
| 925   __ ret(0); | 925   __ ret(0); | 
| 926 } | 926 } | 
| 927 | 927 | 
| 928 | 928 | 
| 929 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, | 929 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, | 
| 930                                                        LookupResult* lookup, | 930                                                        LookupResult* lookup, | 
| 931                                                        Handle<Name> name) { | 931                                                        Handle<Name> name) { | 
| 932   ASSERT(holder()->HasNamedInterceptor()); | 932   DCHECK(holder()->HasNamedInterceptor()); | 
| 933   ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); | 933   DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); | 
| 934 | 934 | 
| 935   // So far the most popular follow ups for interceptor loads are FIELD | 935   // So far the most popular follow ups for interceptor loads are FIELD | 
| 936   // and CALLBACKS, so inline only them, other cases may be added | 936   // and CALLBACKS, so inline only them, other cases may be added | 
| 937   // later. | 937   // later. | 
| 938   bool compile_followup_inline = false; | 938   bool compile_followup_inline = false; | 
| 939   if (lookup->IsFound() && lookup->IsCacheable()) { | 939   if (lookup->IsFound() && lookup->IsCacheable()) { | 
| 940     if (lookup->IsField()) { | 940     if (lookup->IsField()) { | 
| 941       compile_followup_inline = true; | 941       compile_followup_inline = true; | 
| 942     } else if (lookup->type() == CALLBACKS && | 942     } else if (lookup->type() == CALLBACKS && | 
| 943                lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 943                lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 
| 944       Handle<ExecutableAccessorInfo> callback( | 944       Handle<ExecutableAccessorInfo> callback( | 
| 945           ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 945           ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 
| 946       compile_followup_inline = | 946       compile_followup_inline = | 
| 947           callback->getter() != NULL && | 947           callback->getter() != NULL && | 
| 948           ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 948           ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 
| 949                                                            type()); | 949                                                            type()); | 
| 950     } | 950     } | 
| 951   } | 951   } | 
| 952 | 952 | 
| 953   if (compile_followup_inline) { | 953   if (compile_followup_inline) { | 
| 954     // Compile the interceptor call, followed by inline code to load the | 954     // Compile the interceptor call, followed by inline code to load the | 
| 955     // property from further up the prototype chain if the call fails. | 955     // property from further up the prototype chain if the call fails. | 
| 956     // Check that the maps haven't changed. | 956     // Check that the maps haven't changed. | 
| 957     ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 957     DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 
| 958 | 958 | 
| 959     // Preserve the receiver register explicitly whenever it is different from | 959     // Preserve the receiver register explicitly whenever it is different from | 
| 960     // the holder and it is needed should the interceptor return without any | 960     // the holder and it is needed should the interceptor return without any | 
| 961     // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 961     // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 
| 962     // the FIELD case might cause a miss during the prototype check. | 962     // the FIELD case might cause a miss during the prototype check. | 
| 963     bool must_perfrom_prototype_check = *holder() != lookup->holder(); | 963     bool must_perfrom_prototype_check = *holder() != lookup->holder(); | 
| 964     bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 964     bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 
| 965         (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 965         (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 
| 966 | 966 | 
| 967     // Save necessary data before invoking an interceptor. | 967     // Save necessary data before invoking an interceptor. | 
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1161   Register name = LoadIC::NameRegister(); | 1161   Register name = LoadIC::NameRegister(); | 
| 1162   static Register registers[] = { receiver, name, ebx, eax, edi, no_reg }; | 1162   static Register registers[] = { receiver, name, ebx, eax, edi, no_reg }; | 
| 1163   return registers; | 1163   return registers; | 
| 1164 } | 1164 } | 
| 1165 | 1165 | 
| 1166 | 1166 | 
| 1167 Register* PropertyAccessCompiler::store_calling_convention() { | 1167 Register* PropertyAccessCompiler::store_calling_convention() { | 
| 1168   // receiver, name, scratch1, scratch2, scratch3. | 1168   // receiver, name, scratch1, scratch2, scratch3. | 
| 1169   Register receiver = StoreIC::ReceiverRegister(); | 1169   Register receiver = StoreIC::ReceiverRegister(); | 
| 1170   Register name = StoreIC::NameRegister(); | 1170   Register name = StoreIC::NameRegister(); | 
| 1171   ASSERT(ebx.is(KeyedStoreIC::MapRegister())); | 1171   DCHECK(ebx.is(KeyedStoreIC::MapRegister())); | 
| 1172   static Register registers[] = { receiver, name, ebx, edi, no_reg }; | 1172   static Register registers[] = { receiver, name, ebx, edi, no_reg }; | 
| 1173   return registers; | 1173   return registers; | 
| 1174 } | 1174 } | 
| 1175 | 1175 | 
| 1176 | 1176 | 
| 1177 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 1177 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 
| 1178 | 1178 | 
| 1179 | 1179 | 
| 1180 #undef __ | 1180 #undef __ | 
| 1181 #define __ ACCESS_MASM(masm) | 1181 #define __ ACCESS_MASM(masm) | 
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1269       __ j(not_equal, &miss); | 1269       __ j(not_equal, &miss); | 
| 1270     } | 1270     } | 
| 1271   } | 1271   } | 
| 1272 | 1272 | 
| 1273   Label number_case; | 1273   Label number_case; | 
| 1274   Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1274   Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 
| 1275   __ JumpIfSmi(receiver(), smi_target); | 1275   __ JumpIfSmi(receiver(), smi_target); | 
| 1276 | 1276 | 
| 1277   // Polymorphic keyed stores may use the map register | 1277   // Polymorphic keyed stores may use the map register | 
| 1278   Register map_reg = scratch1(); | 1278   Register map_reg = scratch1(); | 
| 1279   ASSERT(kind() != Code::KEYED_STORE_IC || | 1279   DCHECK(kind() != Code::KEYED_STORE_IC || | 
| 1280          map_reg.is(KeyedStoreIC::MapRegister())); | 1280          map_reg.is(KeyedStoreIC::MapRegister())); | 
| 1281   __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | 1281   __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | 
| 1282   int receiver_count = types->length(); | 1282   int receiver_count = types->length(); | 
| 1283   int number_of_handled_maps = 0; | 1283   int number_of_handled_maps = 0; | 
| 1284   for (int current = 0; current < receiver_count; ++current) { | 1284   for (int current = 0; current < receiver_count; ++current) { | 
| 1285     Handle<HeapType> type = types->at(current); | 1285     Handle<HeapType> type = types->at(current); | 
| 1286     Handle<Map> map = IC::TypeToMap(*type, isolate()); | 1286     Handle<Map> map = IC::TypeToMap(*type, isolate()); | 
| 1287     if (!map->is_deprecated()) { | 1287     if (!map->is_deprecated()) { | 
| 1288       number_of_handled_maps++; | 1288       number_of_handled_maps++; | 
| 1289       __ cmp(map_reg, map); | 1289       __ cmp(map_reg, map); | 
| 1290       if (type->Is(HeapType::Number())) { | 1290       if (type->Is(HeapType::Number())) { | 
| 1291         ASSERT(!number_case.is_unused()); | 1291         DCHECK(!number_case.is_unused()); | 
| 1292         __ bind(&number_case); | 1292         __ bind(&number_case); | 
| 1293       } | 1293       } | 
| 1294       __ j(equal, handlers->at(current)); | 1294       __ j(equal, handlers->at(current)); | 
| 1295     } | 1295     } | 
| 1296   } | 1296   } | 
| 1297   ASSERT(number_of_handled_maps != 0); | 1297   DCHECK(number_of_handled_maps != 0); | 
| 1298 | 1298 | 
| 1299   __ bind(&miss); | 1299   __ bind(&miss); | 
| 1300   TailCallBuiltin(masm(), MissBuiltin(kind())); | 1300   TailCallBuiltin(masm(), MissBuiltin(kind())); | 
| 1301 | 1301 | 
| 1302   // Return the generated code. | 1302   // Return the generated code. | 
| 1303   InlineCacheState state = | 1303   InlineCacheState state = | 
| 1304       number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 1304       number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 
| 1305   return GetCode(kind(), type, name, state); | 1305   return GetCode(kind(), type, name, state); | 
| 1306 } | 1306 } | 
| 1307 | 1307 | 
| 1308 | 1308 | 
| 1309 #undef __ | 1309 #undef __ | 
| 1310 #define __ ACCESS_MASM(masm) | 1310 #define __ ACCESS_MASM(masm) | 
| 1311 | 1311 | 
| 1312 | 1312 | 
| 1313 void ElementHandlerCompiler::GenerateLoadDictionaryElement( | 1313 void ElementHandlerCompiler::GenerateLoadDictionaryElement( | 
| 1314     MacroAssembler* masm) { | 1314     MacroAssembler* masm) { | 
| 1315   // ----------- S t a t e ------------- | 1315   // ----------- S t a t e ------------- | 
| 1316   //  -- ecx    : key | 1316   //  -- ecx    : key | 
| 1317   //  -- edx    : receiver | 1317   //  -- edx    : receiver | 
| 1318   //  -- esp[0] : return address | 1318   //  -- esp[0] : return address | 
| 1319   // ----------------------------------- | 1319   // ----------------------------------- | 
| 1320   ASSERT(edx.is(LoadIC::ReceiverRegister())); | 1320   DCHECK(edx.is(LoadIC::ReceiverRegister())); | 
| 1321   ASSERT(ecx.is(LoadIC::NameRegister())); | 1321   DCHECK(ecx.is(LoadIC::NameRegister())); | 
| 1322   Label slow, miss; | 1322   Label slow, miss; | 
| 1323 | 1323 | 
| 1324   // This stub is meant to be tail-jumped to, the receiver must already | 1324   // This stub is meant to be tail-jumped to, the receiver must already | 
| 1325   // have been verified by the caller to not be a smi. | 1325   // have been verified by the caller to not be a smi. | 
| 1326   __ JumpIfNotSmi(ecx, &miss); | 1326   __ JumpIfNotSmi(ecx, &miss); | 
| 1327   __ mov(ebx, ecx); | 1327   __ mov(ebx, ecx); | 
| 1328   __ SmiUntag(ebx); | 1328   __ SmiUntag(ebx); | 
| 1329   __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); | 1329   __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); | 
| 1330 | 1330 | 
| 1331   // Push receiver on the stack to free up a register for the dictionary | 1331   // Push receiver on the stack to free up a register for the dictionary | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 1354   // ----------------------------------- | 1354   // ----------------------------------- | 
| 1355   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1355   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 
| 1356 } | 1356 } | 
| 1357 | 1357 | 
| 1358 | 1358 | 
| 1359 #undef __ | 1359 #undef __ | 
| 1360 | 1360 | 
| 1361 } }  // namespace v8::internal | 1361 } }  // namespace v8::internal | 
| 1362 | 1362 | 
| 1363 #endif  // V8_TARGET_ARCH_X87 | 1363 #endif  // V8_TARGET_ARCH_X87 | 
| OLD | NEW | 
|---|