| 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_MIPS64 |     7 #if V8_TARGET_ARCH_MIPS64 | 
|     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 18 matching lines...) Expand all  Loading... | 
|    29                        Register offset_scratch) { |    29                        Register offset_scratch) { | 
|    30   ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); |    30   ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); | 
|    31   ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |    31   ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); | 
|    32   ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); |    32   ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); | 
|    33  |    33  | 
|    34   uint64_t key_off_addr = reinterpret_cast<uint64_t>(key_offset.address()); |    34   uint64_t key_off_addr = reinterpret_cast<uint64_t>(key_offset.address()); | 
|    35   uint64_t value_off_addr = reinterpret_cast<uint64_t>(value_offset.address()); |    35   uint64_t value_off_addr = reinterpret_cast<uint64_t>(value_offset.address()); | 
|    36   uint64_t map_off_addr = reinterpret_cast<uint64_t>(map_offset.address()); |    36   uint64_t map_off_addr = reinterpret_cast<uint64_t>(map_offset.address()); | 
|    37  |    37  | 
|    38   // Check the relative positions of the address fields. |    38   // Check the relative positions of the address fields. | 
|    39   ASSERT(value_off_addr > key_off_addr); |    39   DCHECK(value_off_addr > key_off_addr); | 
|    40   ASSERT((value_off_addr - key_off_addr) % 4 == 0); |    40   DCHECK((value_off_addr - key_off_addr) % 4 == 0); | 
|    41   ASSERT((value_off_addr - key_off_addr) < (256 * 4)); |    41   DCHECK((value_off_addr - key_off_addr) < (256 * 4)); | 
|    42   ASSERT(map_off_addr > key_off_addr); |    42   DCHECK(map_off_addr > key_off_addr); | 
|    43   ASSERT((map_off_addr - key_off_addr) % 4 == 0); |    43   DCHECK((map_off_addr - key_off_addr) % 4 == 0); | 
|    44   ASSERT((map_off_addr - key_off_addr) < (256 * 4)); |    44   DCHECK((map_off_addr - key_off_addr) < (256 * 4)); | 
|    45  |    45  | 
|    46   Label miss; |    46   Label miss; | 
|    47   Register base_addr = scratch; |    47   Register base_addr = scratch; | 
|    48   scratch = no_reg; |    48   scratch = no_reg; | 
|    49  |    49  | 
|    50   // Multiply by 3 because there are 3 fields per entry (name, code, map). |    50   // Multiply by 3 because there are 3 fields per entry (name, code, map). | 
|    51   __ dsll(offset_scratch, offset, 1); |    51   __ dsll(offset_scratch, offset, 1); | 
|    52   __ Daddu(offset_scratch, offset_scratch, offset); |    52   __ Daddu(offset_scratch, offset_scratch, offset); | 
|    53  |    53  | 
|    54   // Calculate the base address of the entry. |    54   // Calculate the base address of the entry. | 
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|    90   __ Jump(at); |    90   __ Jump(at); | 
|    91  |    91  | 
|    92   // Miss: fall through. |    92   // Miss: fall through. | 
|    93   __ bind(&miss); |    93   __ bind(&miss); | 
|    94 } |    94 } | 
|    95  |    95  | 
|    96  |    96  | 
|    97 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |    97 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 
|    98     MacroAssembler* masm, Label* miss_label, Register receiver, |    98     MacroAssembler* masm, Label* miss_label, Register receiver, | 
|    99     Handle<Name> name, Register scratch0, Register scratch1) { |    99     Handle<Name> name, Register scratch0, Register scratch1) { | 
|   100   ASSERT(name->IsUniqueName()); |   100   DCHECK(name->IsUniqueName()); | 
|   101   ASSERT(!receiver.is(scratch0)); |   101   DCHECK(!receiver.is(scratch0)); | 
|   102   Counters* counters = masm->isolate()->counters(); |   102   Counters* counters = masm->isolate()->counters(); | 
|   103   __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |   103   __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 
|   104   __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |   104   __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 
|   105  |   105  | 
|   106   Label done; |   106   Label done; | 
|   107  |   107  | 
|   108   const int kInterceptorOrAccessCheckNeededMask = |   108   const int kInterceptorOrAccessCheckNeededMask = | 
|   109       (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |   109       (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 
|   110  |   110  | 
|   111   // Bail out if the receiver has a named interceptor or requires access checks. |   111   // Bail out if the receiver has a named interceptor or requires access checks. | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   150                               Register name, |   150                               Register name, | 
|   151                               Register scratch, |   151                               Register scratch, | 
|   152                               Register extra, |   152                               Register extra, | 
|   153                               Register extra2, |   153                               Register extra2, | 
|   154                               Register extra3) { |   154                               Register extra3) { | 
|   155   Isolate* isolate = masm->isolate(); |   155   Isolate* isolate = masm->isolate(); | 
|   156   Label miss; |   156   Label miss; | 
|   157  |   157  | 
|   158   // Make sure that code is valid. The multiplying code relies on the |   158   // Make sure that code is valid. The multiplying code relies on the | 
|   159   // entry size being 12. |   159   // entry size being 12. | 
|   160   // ASSERT(sizeof(Entry) == 12); |   160   // DCHECK(sizeof(Entry) == 12); | 
|   161   // ASSERT(sizeof(Entry) == 3 * kPointerSize); |   161   // DCHECK(sizeof(Entry) == 3 * kPointerSize); | 
|   162  |   162  | 
|   163   // Make sure the flags does not name a specific type. |   163   // Make sure the flags does not name a specific type. | 
|   164   ASSERT(Code::ExtractTypeFromFlags(flags) == 0); |   164   DCHECK(Code::ExtractTypeFromFlags(flags) == 0); | 
|   165  |   165  | 
|   166   // Make sure that there are no register conflicts. |   166   // Make sure that there are no register conflicts. | 
|   167   ASSERT(!scratch.is(receiver)); |   167   DCHECK(!scratch.is(receiver)); | 
|   168   ASSERT(!scratch.is(name)); |   168   DCHECK(!scratch.is(name)); | 
|   169   ASSERT(!extra.is(receiver)); |   169   DCHECK(!extra.is(receiver)); | 
|   170   ASSERT(!extra.is(name)); |   170   DCHECK(!extra.is(name)); | 
|   171   ASSERT(!extra.is(scratch)); |   171   DCHECK(!extra.is(scratch)); | 
|   172   ASSERT(!extra2.is(receiver)); |   172   DCHECK(!extra2.is(receiver)); | 
|   173   ASSERT(!extra2.is(name)); |   173   DCHECK(!extra2.is(name)); | 
|   174   ASSERT(!extra2.is(scratch)); |   174   DCHECK(!extra2.is(scratch)); | 
|   175   ASSERT(!extra2.is(extra)); |   175   DCHECK(!extra2.is(extra)); | 
|   176  |   176  | 
|   177   // Check register validity. |   177   // Check register validity. | 
|   178   ASSERT(!scratch.is(no_reg)); |   178   DCHECK(!scratch.is(no_reg)); | 
|   179   ASSERT(!extra.is(no_reg)); |   179   DCHECK(!extra.is(no_reg)); | 
|   180   ASSERT(!extra2.is(no_reg)); |   180   DCHECK(!extra2.is(no_reg)); | 
|   181   ASSERT(!extra3.is(no_reg)); |   181   DCHECK(!extra3.is(no_reg)); | 
|   182  |   182  | 
|   183   Counters* counters = masm->isolate()->counters(); |   183   Counters* counters = masm->isolate()->counters(); | 
|   184   __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, |   184   __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, | 
|   185                       extra2, extra3); |   185                       extra2, extra3); | 
|   186  |   186  | 
|   187   // Check that the receiver isn't a smi. |   187   // Check that the receiver isn't a smi. | 
|   188   __ JumpIfSmi(receiver, &miss); |   188   __ JumpIfSmi(receiver, &miss); | 
|   189  |   189  | 
|   190   // Get the map of the receiver and compute the hash. |   190   // Get the map of the receiver and compute the hash. | 
|   191   __ ld(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); |   191   __ ld(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); | 
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   266   __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |   266   __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 
|   267   __ Ret(USE_DELAY_SLOT); |   267   __ Ret(USE_DELAY_SLOT); | 
|   268   __ mov(v0, scratch1); |   268   __ mov(v0, scratch1); | 
|   269 } |   269 } | 
|   270  |   270  | 
|   271  |   271  | 
|   272 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |   272 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 
|   273     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |   273     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 
|   274     Register scratch, Label* miss) { |   274     Register scratch, Label* miss) { | 
|   275   Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |   275   Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 
|   276   ASSERT(cell->value()->IsTheHole()); |   276   DCHECK(cell->value()->IsTheHole()); | 
|   277   __ li(scratch, Operand(cell)); |   277   __ li(scratch, Operand(cell)); | 
|   278   __ ld(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |   278   __ ld(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 
|   279   __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |   279   __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 
|   280   __ Branch(miss, ne, scratch, Operand(at)); |   280   __ Branch(miss, ne, scratch, Operand(at)); | 
|   281 } |   281 } | 
|   282  |   282  | 
|   283  |   283  | 
|   284 // Generate StoreTransition code, value is passed in a0 register. |   284 // Generate StoreTransition code, value is passed in a0 register. | 
|   285 // After executing generated code, the receiver_reg and name_reg |   285 // After executing generated code, the receiver_reg and name_reg | 
|   286 // may be clobbered. |   286 // may be clobbered. | 
|   287 void NamedStoreHandlerCompiler::GenerateStoreTransition( |   287 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 
|   288     MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |   288     MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, | 
|   289     Handle<Name> name, Register receiver_reg, Register storage_reg, |   289     Handle<Name> name, Register receiver_reg, Register storage_reg, | 
|   290     Register value_reg, Register scratch1, Register scratch2, Register scratch3, |   290     Register value_reg, Register scratch1, Register scratch2, Register scratch3, | 
|   291     Label* miss_label, Label* slow) { |   291     Label* miss_label, Label* slow) { | 
|   292   // a0 : value. |   292   // a0 : value. | 
|   293   Label exit; |   293   Label exit; | 
|   294  |   294  | 
|   295   int descriptor = transition->LastAdded(); |   295   int descriptor = transition->LastAdded(); | 
|   296   DescriptorArray* descriptors = transition->instance_descriptors(); |   296   DescriptorArray* descriptors = transition->instance_descriptors(); | 
|   297   PropertyDetails details = descriptors->GetDetails(descriptor); |   297   PropertyDetails details = descriptors->GetDetails(descriptor); | 
|   298   Representation representation = details.representation(); |   298   Representation representation = details.representation(); | 
|   299   ASSERT(!representation.IsNone()); |   299   DCHECK(!representation.IsNone()); | 
|   300  |   300  | 
|   301   if (details.type() == CONSTANT) { |   301   if (details.type() == CONSTANT) { | 
|   302     Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |   302     Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 
|   303     __ li(scratch1, constant); |   303     __ li(scratch1, constant); | 
|   304     __ Branch(miss_label, ne, value_reg, Operand(scratch1)); |   304     __ Branch(miss_label, ne, value_reg, Operand(scratch1)); | 
|   305   } else if (representation.IsSmi()) { |   305   } else if (representation.IsSmi()) { | 
|   306     __ JumpIfNotSmi(value_reg, miss_label); |   306     __ JumpIfNotSmi(value_reg, miss_label); | 
|   307   } else if (representation.IsHeapObject()) { |   307   } else if (representation.IsHeapObject()) { | 
|   308     __ JumpIfSmi(value_reg, miss_label); |   308     __ JumpIfSmi(value_reg, miss_label); | 
|   309     HeapType* field_type = descriptors->GetFieldType(descriptor); |   309     HeapType* field_type = descriptors->GetFieldType(descriptor); | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
|   339     __ bind(&heap_number); |   339     __ bind(&heap_number); | 
|   340     __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |   340     __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, | 
|   341                 miss_label, DONT_DO_SMI_CHECK); |   341                 miss_label, DONT_DO_SMI_CHECK); | 
|   342     __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |   342     __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 
|   343  |   343  | 
|   344     __ bind(&do_store); |   344     __ bind(&do_store); | 
|   345     __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); |   345     __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); | 
|   346   } |   346   } | 
|   347  |   347  | 
|   348   // Stub never generated for objects that require access checks. |   348   // Stub never generated for objects that require access checks. | 
|   349   ASSERT(!transition->is_access_check_needed()); |   349   DCHECK(!transition->is_access_check_needed()); | 
|   350  |   350  | 
|   351   // Perform map transition for the receiver if necessary. |   351   // Perform map transition for the receiver if necessary. | 
|   352   if (details.type() == FIELD && |   352   if (details.type() == FIELD && | 
|   353       Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |   353       Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 
|   354     // The properties must be extended before we can store the value. |   354     // The properties must be extended before we can store the value. | 
|   355     // We jump to a runtime call that extends the properties array. |   355     // We jump to a runtime call that extends the properties array. | 
|   356     __ push(receiver_reg); |   356     __ push(receiver_reg); | 
|   357     __ li(a2, Operand(transition)); |   357     __ li(a2, Operand(transition)); | 
|   358     __ Push(a2, a0); |   358     __ Push(a2, a0); | 
|   359     __ TailCallExternalReference( |   359     __ TailCallExternalReference( | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|   371   __ RecordWriteField(receiver_reg, |   371   __ RecordWriteField(receiver_reg, | 
|   372                       HeapObject::kMapOffset, |   372                       HeapObject::kMapOffset, | 
|   373                       scratch1, |   373                       scratch1, | 
|   374                       scratch2, |   374                       scratch2, | 
|   375                       kRAHasNotBeenSaved, |   375                       kRAHasNotBeenSaved, | 
|   376                       kDontSaveFPRegs, |   376                       kDontSaveFPRegs, | 
|   377                       OMIT_REMEMBERED_SET, |   377                       OMIT_REMEMBERED_SET, | 
|   378                       OMIT_SMI_CHECK); |   378                       OMIT_SMI_CHECK); | 
|   379  |   379  | 
|   380   if (details.type() == CONSTANT) { |   380   if (details.type() == CONSTANT) { | 
|   381     ASSERT(value_reg.is(a0)); |   381     DCHECK(value_reg.is(a0)); | 
|   382     __ Ret(USE_DELAY_SLOT); |   382     __ Ret(USE_DELAY_SLOT); | 
|   383     __ mov(v0, a0); |   383     __ mov(v0, a0); | 
|   384     return; |   384     return; | 
|   385   } |   385   } | 
|   386  |   386  | 
|   387   int index = transition->instance_descriptors()->GetFieldIndex( |   387   int index = transition->instance_descriptors()->GetFieldIndex( | 
|   388       transition->LastAdded()); |   388       transition->LastAdded()); | 
|   389  |   389  | 
|   390   // Adjust for the number of properties stored in the object. Even in the |   390   // Adjust for the number of properties stored in the object. Even in the | 
|   391   // face of a transition we can use the old map here because the size of the |   391   // face of a transition we can use the old map here because the size of the | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   440                           storage_reg, |   440                           storage_reg, | 
|   441                           receiver_reg, |   441                           receiver_reg, | 
|   442                           kRAHasNotBeenSaved, |   442                           kRAHasNotBeenSaved, | 
|   443                           kDontSaveFPRegs, |   443                           kDontSaveFPRegs, | 
|   444                           EMIT_REMEMBERED_SET, |   444                           EMIT_REMEMBERED_SET, | 
|   445                           smi_check); |   445                           smi_check); | 
|   446     } |   446     } | 
|   447   } |   447   } | 
|   448  |   448  | 
|   449   // Return the value (register v0). |   449   // Return the value (register v0). | 
|   450   ASSERT(value_reg.is(a0)); |   450   DCHECK(value_reg.is(a0)); | 
|   451   __ bind(&exit); |   451   __ bind(&exit); | 
|   452   __ Ret(USE_DELAY_SLOT); |   452   __ Ret(USE_DELAY_SLOT); | 
|   453   __ mov(v0, a0); |   453   __ mov(v0, a0); | 
|   454 } |   454 } | 
|   455  |   455  | 
|   456  |   456  | 
|   457 // Generate StoreField code, value is passed in a0 register. |   457 // Generate StoreField code, value is passed in a0 register. | 
|   458 // When leaving generated code after success, the receiver_reg and name_reg |   458 // When leaving generated code after success, the receiver_reg and name_reg | 
|   459 // may be clobbered.  Upon branch to miss_label, the receiver and name |   459 // may be clobbered.  Upon branch to miss_label, the receiver and name | 
|   460 // registers have their original values. |   460 // registers have their original values. | 
|   461 void NamedStoreHandlerCompiler::GenerateStoreField( |   461 void NamedStoreHandlerCompiler::GenerateStoreField( | 
|   462     MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |   462     MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 
|   463     Register receiver_reg, Register name_reg, Register value_reg, |   463     Register receiver_reg, Register name_reg, Register value_reg, | 
|   464     Register scratch1, Register scratch2, Label* miss_label) { |   464     Register scratch1, Register scratch2, Label* miss_label) { | 
|   465   // a0 : value |   465   // a0 : value | 
|   466   Label exit; |   466   Label exit; | 
|   467  |   467  | 
|   468   // Stub never generated for non-global objects that require access |   468   // Stub never generated for non-global objects that require access | 
|   469   // checks. |   469   // checks. | 
|   470   ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |   470   DCHECK(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 
|   471  |   471  | 
|   472   FieldIndex index = lookup->GetFieldIndex(); |   472   FieldIndex index = lookup->GetFieldIndex(); | 
|   473  |   473  | 
|   474   Representation representation = lookup->representation(); |   474   Representation representation = lookup->representation(); | 
|   475   ASSERT(!representation.IsNone()); |   475   DCHECK(!representation.IsNone()); | 
|   476   if (representation.IsSmi()) { |   476   if (representation.IsSmi()) { | 
|   477     __ JumpIfNotSmi(value_reg, miss_label); |   477     __ JumpIfNotSmi(value_reg, miss_label); | 
|   478   } else if (representation.IsHeapObject()) { |   478   } else if (representation.IsHeapObject()) { | 
|   479     __ JumpIfSmi(value_reg, miss_label); |   479     __ JumpIfSmi(value_reg, miss_label); | 
|   480     HeapType* field_type = lookup->GetFieldType(); |   480     HeapType* field_type = lookup->GetFieldType(); | 
|   481     HeapType::Iterator<Map> it = field_type->Classes(); |   481     HeapType::Iterator<Map> it = field_type->Classes(); | 
|   482     if (!it.Done()) { |   482     if (!it.Done()) { | 
|   483       __ ld(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |   483       __ ld(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 
|   484       Label do_store; |   484       Label do_store; | 
|   485       Handle<Map> current; |   485       Handle<Map> current; | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
|   514     __ jmp(&do_store); |   514     __ jmp(&do_store); | 
|   515  |   515  | 
|   516     __ bind(&heap_number); |   516     __ bind(&heap_number); | 
|   517     __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, |   517     __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, | 
|   518                 miss_label, DONT_DO_SMI_CHECK); |   518                 miss_label, DONT_DO_SMI_CHECK); | 
|   519     __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |   519     __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 
|   520  |   520  | 
|   521     __ bind(&do_store); |   521     __ bind(&do_store); | 
|   522     __ sdc1(f4, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); |   522     __ sdc1(f4, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); | 
|   523     // Return the value (register v0). |   523     // Return the value (register v0). | 
|   524     ASSERT(value_reg.is(a0)); |   524     DCHECK(value_reg.is(a0)); | 
|   525     __ Ret(USE_DELAY_SLOT); |   525     __ Ret(USE_DELAY_SLOT); | 
|   526     __ mov(v0, a0); |   526     __ mov(v0, a0); | 
|   527     return; |   527     return; | 
|   528   } |   528   } | 
|   529  |   529  | 
|   530   // TODO(verwaest): Share this code as a code stub. |   530   // TODO(verwaest): Share this code as a code stub. | 
|   531   SmiCheck smi_check = representation.IsTagged() |   531   SmiCheck smi_check = representation.IsTagged() | 
|   532       ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |   532       ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 
|   533   if (index.is_inobject()) { |   533   if (index.is_inobject()) { | 
|   534     // Set the property straight into the object. |   534     // Set the property straight into the object. | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   569                           name_reg, |   569                           name_reg, | 
|   570                           receiver_reg, |   570                           receiver_reg, | 
|   571                           kRAHasNotBeenSaved, |   571                           kRAHasNotBeenSaved, | 
|   572                           kDontSaveFPRegs, |   572                           kDontSaveFPRegs, | 
|   573                           EMIT_REMEMBERED_SET, |   573                           EMIT_REMEMBERED_SET, | 
|   574                           smi_check); |   574                           smi_check); | 
|   575     } |   575     } | 
|   576   } |   576   } | 
|   577  |   577  | 
|   578   // Return the value (register v0). |   578   // Return the value (register v0). | 
|   579   ASSERT(value_reg.is(a0)); |   579   DCHECK(value_reg.is(a0)); | 
|   580   __ bind(&exit); |   580   __ bind(&exit); | 
|   581   __ Ret(USE_DELAY_SLOT); |   581   __ Ret(USE_DELAY_SLOT); | 
|   582   __ mov(v0, a0); |   582   __ mov(v0, a0); | 
|   583 } |   583 } | 
|   584  |   584  | 
|   585  |   585  | 
|   586 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, |   586 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, | 
|   587                                                     Label* label, |   587                                                     Label* label, | 
|   588                                                     Handle<Name> name) { |   588                                                     Handle<Name> name) { | 
|   589   if (!label->is_unused()) { |   589   if (!label->is_unused()) { | 
|   590     __ bind(label); |   590     __ bind(label); | 
|   591     __ li(this->name(), Operand(name)); |   591     __ li(this->name(), Operand(name)); | 
|   592   } |   592   } | 
|   593 } |   593 } | 
|   594  |   594  | 
|   595  |   595  | 
|   596 static void PushInterceptorArguments(MacroAssembler* masm, |   596 static void PushInterceptorArguments(MacroAssembler* masm, | 
|   597                                      Register receiver, |   597                                      Register receiver, | 
|   598                                      Register holder, |   598                                      Register holder, | 
|   599                                      Register name, |   599                                      Register name, | 
|   600                                      Handle<JSObject> holder_obj) { |   600                                      Handle<JSObject> holder_obj) { | 
|   601   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); |   601   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 
|   602   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); |   602   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); | 
|   603   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); |   603   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); | 
|   604   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); |   604   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); | 
|   605   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); |   605   STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); | 
|   606   __ push(name); |   606   __ push(name); | 
|   607   Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |   607   Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 
|   608   ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |   608   DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 
|   609   Register scratch = name; |   609   Register scratch = name; | 
|   610   __ li(scratch, Operand(interceptor)); |   610   __ li(scratch, Operand(interceptor)); | 
|   611   __ Push(scratch, receiver, holder); |   611   __ Push(scratch, receiver, holder); | 
|   612 } |   612 } | 
|   613  |   613  | 
|   614  |   614  | 
|   615 static void CompileCallLoadPropertyWithInterceptor( |   615 static void CompileCallLoadPropertyWithInterceptor( | 
|   616     MacroAssembler* masm, |   616     MacroAssembler* masm, | 
|   617     Register receiver, |   617     Register receiver, | 
|   618     Register holder, |   618     Register holder, | 
|   619     Register name, |   619     Register name, | 
|   620     Handle<JSObject> holder_obj, |   620     Handle<JSObject> holder_obj, | 
|   621     IC::UtilityId id) { |   621     IC::UtilityId id) { | 
|   622   PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |   622   PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 
|   623   __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), |   623   __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), | 
|   624                            NamedLoadHandlerCompiler::kInterceptorArgsLength); |   624                            NamedLoadHandlerCompiler::kInterceptorArgsLength); | 
|   625 } |   625 } | 
|   626  |   626  | 
|   627  |   627  | 
|   628 // Generate call to api function. |   628 // Generate call to api function. | 
|   629 void PropertyHandlerCompiler::GenerateFastApiCall( |   629 void PropertyHandlerCompiler::GenerateFastApiCall( | 
|   630     MacroAssembler* masm, const CallOptimization& optimization, |   630     MacroAssembler* masm, const CallOptimization& optimization, | 
|   631     Handle<Map> receiver_map, Register receiver, Register scratch_in, |   631     Handle<Map> receiver_map, Register receiver, Register scratch_in, | 
|   632     bool is_store, int argc, Register* values) { |   632     bool is_store, int argc, Register* values) { | 
|   633   ASSERT(!receiver.is(scratch_in)); |   633   DCHECK(!receiver.is(scratch_in)); | 
|   634   // Preparing to push, adjust sp. |   634   // Preparing to push, adjust sp. | 
|   635   __ Dsubu(sp, sp, Operand((argc + 1) * kPointerSize)); |   635   __ Dsubu(sp, sp, Operand((argc + 1) * kPointerSize)); | 
|   636   __ sd(receiver, MemOperand(sp, argc * kPointerSize));  // Push receiver. |   636   __ sd(receiver, MemOperand(sp, argc * kPointerSize));  // Push receiver. | 
|   637   // Write the arguments to stack frame. |   637   // Write the arguments to stack frame. | 
|   638   for (int i = 0; i < argc; i++) { |   638   for (int i = 0; i < argc; i++) { | 
|   639     Register arg = values[argc-1-i]; |   639     Register arg = values[argc-1-i]; | 
|   640     ASSERT(!receiver.is(arg)); |   640     DCHECK(!receiver.is(arg)); | 
|   641     ASSERT(!scratch_in.is(arg)); |   641     DCHECK(!scratch_in.is(arg)); | 
|   642     __ sd(arg, MemOperand(sp, (argc-1-i) * kPointerSize));  // Push arg. |   642     __ sd(arg, MemOperand(sp, (argc-1-i) * kPointerSize));  // Push arg. | 
|   643   } |   643   } | 
|   644   ASSERT(optimization.is_simple_api_call()); |   644   DCHECK(optimization.is_simple_api_call()); | 
|   645  |   645  | 
|   646   // Abi for CallApiFunctionStub. |   646   // Abi for CallApiFunctionStub. | 
|   647   Register callee = a0; |   647   Register callee = a0; | 
|   648   Register call_data = a4; |   648   Register call_data = a4; | 
|   649   Register holder = a2; |   649   Register holder = a2; | 
|   650   Register api_function_address = a1; |   650   Register api_function_address = a1; | 
|   651  |   651  | 
|   652   // Put holder in place. |   652   // Put holder in place. | 
|   653   CallOptimization::HolderLookup holder_lookup; |   653   CallOptimization::HolderLookup holder_lookup; | 
|   654   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( |   654   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( | 
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   711 #define __ ACCESS_MASM(masm()) |   711 #define __ ACCESS_MASM(masm()) | 
|   712  |   712  | 
|   713  |   713  | 
|   714 Register PropertyHandlerCompiler::CheckPrototypes( |   714 Register PropertyHandlerCompiler::CheckPrototypes( | 
|   715     Register object_reg, Register holder_reg, Register scratch1, |   715     Register object_reg, Register holder_reg, Register scratch1, | 
|   716     Register scratch2, Handle<Name> name, Label* miss, |   716     Register scratch2, Handle<Name> name, Label* miss, | 
|   717     PrototypeCheckType check) { |   717     PrototypeCheckType check) { | 
|   718   Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |   718   Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 
|   719  |   719  | 
|   720   // Make sure there's no overlap between holder and object registers. |   720   // Make sure there's no overlap between holder and object registers. | 
|   721   ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |   721   DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 
|   722   ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |   722   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 
|   723          && !scratch2.is(scratch1)); |   723          && !scratch2.is(scratch1)); | 
|   724  |   724  | 
|   725   // Keep track of the current object in register reg. |   725   // Keep track of the current object in register reg. | 
|   726   Register reg = object_reg; |   726   Register reg = object_reg; | 
|   727   int depth = 0; |   727   int depth = 0; | 
|   728  |   728  | 
|   729   Handle<JSObject> current = Handle<JSObject>::null(); |   729   Handle<JSObject> current = Handle<JSObject>::null(); | 
|   730   if (type()->IsConstant()) { |   730   if (type()->IsConstant()) { | 
|   731     current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |   731     current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 
|   732   } |   732   } | 
|   733   Handle<JSObject> prototype = Handle<JSObject>::null(); |   733   Handle<JSObject> prototype = Handle<JSObject>::null(); | 
|   734   Handle<Map> current_map = receiver_map; |   734   Handle<Map> current_map = receiver_map; | 
|   735   Handle<Map> holder_map(holder()->map()); |   735   Handle<Map> holder_map(holder()->map()); | 
|   736   // Traverse the prototype chain and check the maps in the prototype chain for |   736   // Traverse the prototype chain and check the maps in the prototype chain for | 
|   737   // fast and global objects or do negative lookup for normal objects. |   737   // fast and global objects or do negative lookup for normal objects. | 
|   738   while (!current_map.is_identical_to(holder_map)) { |   738   while (!current_map.is_identical_to(holder_map)) { | 
|   739     ++depth; |   739     ++depth; | 
|   740  |   740  | 
|   741     // Only global objects and objects that do not require access |   741     // Only global objects and objects that do not require access | 
|   742     // checks are allowed in stubs. |   742     // checks are allowed in stubs. | 
|   743     ASSERT(current_map->IsJSGlobalProxyMap() || |   743     DCHECK(current_map->IsJSGlobalProxyMap() || | 
|   744            !current_map->is_access_check_needed()); |   744            !current_map->is_access_check_needed()); | 
|   745  |   745  | 
|   746     prototype = handle(JSObject::cast(current_map->prototype())); |   746     prototype = handle(JSObject::cast(current_map->prototype())); | 
|   747     if (current_map->is_dictionary_map() && |   747     if (current_map->is_dictionary_map() && | 
|   748         !current_map->IsJSGlobalObjectMap() && |   748         !current_map->IsJSGlobalObjectMap() && | 
|   749         !current_map->IsJSGlobalProxyMap()) { |   749         !current_map->IsJSGlobalProxyMap()) { | 
|   750       if (!name->IsUniqueName()) { |   750       if (!name->IsUniqueName()) { | 
|   751         ASSERT(name->IsString()); |   751         DCHECK(name->IsString()); | 
|   752         name = factory()->InternalizeString(Handle<String>::cast(name)); |   752         name = factory()->InternalizeString(Handle<String>::cast(name)); | 
|   753       } |   753       } | 
|   754       ASSERT(current.is_null() || |   754       DCHECK(current.is_null() || | 
|   755              current->property_dictionary()->FindEntry(name) == |   755              current->property_dictionary()->FindEntry(name) == | 
|   756              NameDictionary::kNotFound); |   756              NameDictionary::kNotFound); | 
|   757  |   757  | 
|   758       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |   758       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 
|   759                                        scratch1, scratch2); |   759                                        scratch1, scratch2); | 
|   760  |   760  | 
|   761       __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |   761       __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 
|   762       reg = holder_reg;  // From now on the object will be in holder_reg. |   762       reg = holder_reg;  // From now on the object will be in holder_reg. | 
|   763       __ ld(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |   763       __ ld(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 
|   764     } else { |   764     } else { | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   803  |   803  | 
|   804   // Log the check depth. |   804   // Log the check depth. | 
|   805   LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |   805   LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 
|   806  |   806  | 
|   807   if (depth != 0 || check == CHECK_ALL_MAPS) { |   807   if (depth != 0 || check == CHECK_ALL_MAPS) { | 
|   808     // Check the holder map. |   808     // Check the holder map. | 
|   809     __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); |   809     __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); | 
|   810   } |   810   } | 
|   811  |   811  | 
|   812   // Perform security check for access to the global object. |   812   // Perform security check for access to the global object. | 
|   813   ASSERT(current_map->IsJSGlobalProxyMap() || |   813   DCHECK(current_map->IsJSGlobalProxyMap() || | 
|   814          !current_map->is_access_check_needed()); |   814          !current_map->is_access_check_needed()); | 
|   815   if (current_map->IsJSGlobalProxyMap()) { |   815   if (current_map->IsJSGlobalProxyMap()) { | 
|   816     __ CheckAccessGlobalProxy(reg, scratch1, miss); |   816     __ CheckAccessGlobalProxy(reg, scratch1, miss); | 
|   817   } |   817   } | 
|   818  |   818  | 
|   819   // Return the register containing the holder. |   819   // Return the register containing the holder. | 
|   820   return reg; |   820   return reg; | 
|   821 } |   821 } | 
|   822  |   822  | 
|   823  |   823  | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|   844  |   844  | 
|   845  |   845  | 
|   846 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |   846 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 
|   847                                                     Handle<Name> name, |   847                                                     Handle<Name> name, | 
|   848                                                     Handle<Object> callback) { |   848                                                     Handle<Object> callback) { | 
|   849   Label miss; |   849   Label miss; | 
|   850  |   850  | 
|   851   Register reg = FrontendHeader(object_reg, name, &miss); |   851   Register reg = FrontendHeader(object_reg, name, &miss); | 
|   852  |   852  | 
|   853   if (!holder()->HasFastProperties()) { |   853   if (!holder()->HasFastProperties()) { | 
|   854     ASSERT(!holder()->IsGlobalObject()); |   854     DCHECK(!holder()->IsGlobalObject()); | 
|   855     ASSERT(!reg.is(scratch2())); |   855     DCHECK(!reg.is(scratch2())); | 
|   856     ASSERT(!reg.is(scratch3())); |   856     DCHECK(!reg.is(scratch3())); | 
|   857     ASSERT(!reg.is(scratch4())); |   857     DCHECK(!reg.is(scratch4())); | 
|   858  |   858  | 
|   859     // Load the properties dictionary. |   859     // Load the properties dictionary. | 
|   860     Register dictionary = scratch4(); |   860     Register dictionary = scratch4(); | 
|   861     __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |   861     __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 
|   862  |   862  | 
|   863     // Probe the dictionary. |   863     // Probe the dictionary. | 
|   864     Label probe_done; |   864     Label probe_done; | 
|   865     NameDictionaryLookupStub::GeneratePositiveLookup(masm(), |   865     NameDictionaryLookupStub::GeneratePositiveLookup(masm(), | 
|   866                                                      &miss, |   866                                                      &miss, | 
|   867                                                      &probe_done, |   867                                                      &probe_done, | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   905     Register reg, Handle<ExecutableAccessorInfo> callback) { |   905     Register reg, Handle<ExecutableAccessorInfo> callback) { | 
|   906   // Build AccessorInfo::args_ list on the stack and push property name below |   906   // Build AccessorInfo::args_ list on the stack and push property name below | 
|   907   // the exit frame to make GC aware of them and store pointers to them. |   907   // the exit frame to make GC aware of them and store pointers to them. | 
|   908   STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |   908   STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 
|   909   STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |   909   STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 
|   910   STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |   910   STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 
|   911   STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |   911   STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 
|   912   STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |   912   STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 
|   913   STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |   913   STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 
|   914   STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); |   914   STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); | 
|   915   ASSERT(!scratch2().is(reg)); |   915   DCHECK(!scratch2().is(reg)); | 
|   916   ASSERT(!scratch3().is(reg)); |   916   DCHECK(!scratch3().is(reg)); | 
|   917   ASSERT(!scratch4().is(reg)); |   917   DCHECK(!scratch4().is(reg)); | 
|   918   __ push(receiver()); |   918   __ push(receiver()); | 
|   919   if (heap()->InNewSpace(callback->data())) { |   919   if (heap()->InNewSpace(callback->data())) { | 
|   920     __ li(scratch3(), callback); |   920     __ li(scratch3(), callback); | 
|   921     __ ld(scratch3(), FieldMemOperand(scratch3(), |   921     __ ld(scratch3(), FieldMemOperand(scratch3(), | 
|   922                                       ExecutableAccessorInfo::kDataOffset)); |   922                                       ExecutableAccessorInfo::kDataOffset)); | 
|   923   } else { |   923   } else { | 
|   924     __ li(scratch3(), Handle<Object>(callback->data(), isolate())); |   924     __ li(scratch3(), Handle<Object>(callback->data(), isolate())); | 
|   925   } |   925   } | 
|   926   __ Dsubu(sp, sp, 6 * kPointerSize); |   926   __ Dsubu(sp, sp, 6 * kPointerSize); | 
|   927   __ sd(scratch3(), MemOperand(sp, 5 * kPointerSize)); |   927   __ sd(scratch3(), MemOperand(sp, 5 * kPointerSize)); | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
|   946   __ li(getter_address_reg, Operand(ref)); |   946   __ li(getter_address_reg, Operand(ref)); | 
|   947  |   947  | 
|   948   CallApiGetterStub stub(isolate()); |   948   CallApiGetterStub stub(isolate()); | 
|   949   __ TailCallStub(&stub); |   949   __ TailCallStub(&stub); | 
|   950 } |   950 } | 
|   951  |   951  | 
|   952  |   952  | 
|   953 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |   953 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, | 
|   954                                                        LookupResult* lookup, |   954                                                        LookupResult* lookup, | 
|   955                                                        Handle<Name> name) { |   955                                                        Handle<Name> name) { | 
|   956   ASSERT(holder()->HasNamedInterceptor()); |   956   DCHECK(holder()->HasNamedInterceptor()); | 
|   957   ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |   957   DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); | 
|   958  |   958  | 
|   959   // So far the most popular follow ups for interceptor loads are FIELD |   959   // So far the most popular follow ups for interceptor loads are FIELD | 
|   960   // and CALLBACKS, so inline only them, other cases may be added |   960   // and CALLBACKS, so inline only them, other cases may be added | 
|   961   // later. |   961   // later. | 
|   962   bool compile_followup_inline = false; |   962   bool compile_followup_inline = false; | 
|   963   if (lookup->IsFound() && lookup->IsCacheable()) { |   963   if (lookup->IsFound() && lookup->IsCacheable()) { | 
|   964     if (lookup->IsField()) { |   964     if (lookup->IsField()) { | 
|   965       compile_followup_inline = true; |   965       compile_followup_inline = true; | 
|   966     } else if (lookup->type() == CALLBACKS && |   966     } else if (lookup->type() == CALLBACKS && | 
|   967         lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |   967         lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 
|   968       Handle<ExecutableAccessorInfo> callback( |   968       Handle<ExecutableAccessorInfo> callback( | 
|   969           ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |   969           ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 
|   970       compile_followup_inline = |   970       compile_followup_inline = | 
|   971           callback->getter() != NULL && |   971           callback->getter() != NULL && | 
|   972           ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |   972           ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 
|   973                                                            type()); |   973                                                            type()); | 
|   974     } |   974     } | 
|   975   } |   975   } | 
|   976  |   976  | 
|   977   if (compile_followup_inline) { |   977   if (compile_followup_inline) { | 
|   978     // Compile the interceptor call, followed by inline code to load the |   978     // Compile the interceptor call, followed by inline code to load the | 
|   979     // property from further up the prototype chain if the call fails. |   979     // property from further up the prototype chain if the call fails. | 
|   980     // Check that the maps haven't changed. |   980     // Check that the maps haven't changed. | 
|   981     ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |   981     DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 
|   982  |   982  | 
|   983     // Preserve the receiver register explicitly whenever it is different from |   983     // Preserve the receiver register explicitly whenever it is different from | 
|   984     // the holder and it is needed should the interceptor return without any |   984     // the holder and it is needed should the interceptor return without any | 
|   985     // result. The CALLBACKS case needs the receiver to be passed into C++ code, |   985     // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 
|   986     // the FIELD case might cause a miss during the prototype check. |   986     // the FIELD case might cause a miss during the prototype check. | 
|   987     bool must_perfrom_prototype_check = *holder() != lookup->holder(); |   987     bool must_perfrom_prototype_check = *holder() != lookup->holder(); | 
|   988     bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |   988     bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 
|   989         (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |   989         (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 
|   990  |   990  | 
|   991     // Save necessary data before invoking an interceptor. |   991     // Save necessary data before invoking an interceptor. | 
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1124   Register name = LoadIC::NameRegister(); |  1124   Register name = LoadIC::NameRegister(); | 
|  1125   static Register registers[] = { receiver, name, a3, a0, a4, a5 }; |  1125   static Register registers[] = { receiver, name, a3, a0, a4, a5 }; | 
|  1126   return registers; |  1126   return registers; | 
|  1127 } |  1127 } | 
|  1128  |  1128  | 
|  1129  |  1129  | 
|  1130 Register* PropertyAccessCompiler::store_calling_convention() { |  1130 Register* PropertyAccessCompiler::store_calling_convention() { | 
|  1131   // receiver, name, scratch1, scratch2, scratch3. |  1131   // receiver, name, scratch1, scratch2, scratch3. | 
|  1132   Register receiver = StoreIC::ReceiverRegister(); |  1132   Register receiver = StoreIC::ReceiverRegister(); | 
|  1133   Register name = StoreIC::NameRegister(); |  1133   Register name = StoreIC::NameRegister(); | 
|  1134   ASSERT(a3.is(KeyedStoreIC::MapRegister())); |  1134   DCHECK(a3.is(KeyedStoreIC::MapRegister())); | 
|  1135   static Register registers[] = { receiver, name, a3, a4, a5 }; |  1135   static Register registers[] = { receiver, name, a3, a4, a5 }; | 
|  1136   return registers; |  1136   return registers; | 
|  1137 } |  1137 } | 
|  1138  |  1138  | 
|  1139  |  1139  | 
|  1140 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |  1140 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 
|  1141  |  1141  | 
|  1142  |  1142  | 
|  1143 #undef __ |  1143 #undef __ | 
|  1144 #define __ ACCESS_MASM(masm) |  1144 #define __ ACCESS_MASM(masm) | 
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1231     } |  1231     } | 
|  1232   } |  1232   } | 
|  1233  |  1233  | 
|  1234   Label number_case; |  1234   Label number_case; | 
|  1235   Register match = scratch2(); |  1235   Register match = scratch2(); | 
|  1236   Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |  1236   Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 
|  1237   __ JumpIfSmi(receiver(), smi_target, match);  // Reg match is 0 if Smi. |  1237   __ JumpIfSmi(receiver(), smi_target, match);  // Reg match is 0 if Smi. | 
|  1238  |  1238  | 
|  1239   // Polymorphic keyed stores may use the map register |  1239   // Polymorphic keyed stores may use the map register | 
|  1240   Register map_reg = scratch1(); |  1240   Register map_reg = scratch1(); | 
|  1241   ASSERT(kind() != Code::KEYED_STORE_IC || |  1241   DCHECK(kind() != Code::KEYED_STORE_IC || | 
|  1242          map_reg.is(KeyedStoreIC::MapRegister())); |  1242          map_reg.is(KeyedStoreIC::MapRegister())); | 
|  1243  |  1243  | 
|  1244   int receiver_count = types->length(); |  1244   int receiver_count = types->length(); | 
|  1245   int number_of_handled_maps = 0; |  1245   int number_of_handled_maps = 0; | 
|  1246   __ ld(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |  1246   __ ld(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 
|  1247   for (int current = 0; current < receiver_count; ++current) { |  1247   for (int current = 0; current < receiver_count; ++current) { | 
|  1248     Handle<HeapType> type = types->at(current); |  1248     Handle<HeapType> type = types->at(current); | 
|  1249     Handle<Map> map = IC::TypeToMap(*type, isolate()); |  1249     Handle<Map> map = IC::TypeToMap(*type, isolate()); | 
|  1250     if (!map->is_deprecated()) { |  1250     if (!map->is_deprecated()) { | 
|  1251       number_of_handled_maps++; |  1251       number_of_handled_maps++; | 
|  1252       // Check map and tail call if there's a match. |  1252       // Check map and tail call if there's a match. | 
|  1253       // Separate compare from branch, to provide path for above JumpIfSmi(). |  1253       // Separate compare from branch, to provide path for above JumpIfSmi(). | 
|  1254       __ Dsubu(match, map_reg, Operand(map)); |  1254       __ Dsubu(match, map_reg, Operand(map)); | 
|  1255       if (type->Is(HeapType::Number())) { |  1255       if (type->Is(HeapType::Number())) { | 
|  1256         ASSERT(!number_case.is_unused()); |  1256         DCHECK(!number_case.is_unused()); | 
|  1257         __ bind(&number_case); |  1257         __ bind(&number_case); | 
|  1258       } |  1258       } | 
|  1259       __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, |  1259       __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, | 
|  1260           eq, match, Operand(zero_reg)); |  1260           eq, match, Operand(zero_reg)); | 
|  1261     } |  1261     } | 
|  1262   } |  1262   } | 
|  1263   ASSERT(number_of_handled_maps != 0); |  1263   DCHECK(number_of_handled_maps != 0); | 
|  1264  |  1264  | 
|  1265   __ bind(&miss); |  1265   __ bind(&miss); | 
|  1266   TailCallBuiltin(masm(), MissBuiltin(kind())); |  1266   TailCallBuiltin(masm(), MissBuiltin(kind())); | 
|  1267  |  1267  | 
|  1268   // Return the generated code. |  1268   // Return the generated code. | 
|  1269   InlineCacheState state = |  1269   InlineCacheState state = | 
|  1270       number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |  1270       number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 
|  1271   return GetCode(kind(), type, name, state); |  1271   return GetCode(kind(), type, name, state); | 
|  1272 } |  1272 } | 
|  1273  |  1273  | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1316 #define __ ACCESS_MASM(masm) |  1316 #define __ ACCESS_MASM(masm) | 
|  1317  |  1317  | 
|  1318  |  1318  | 
|  1319 void ElementHandlerCompiler::GenerateLoadDictionaryElement( |  1319 void ElementHandlerCompiler::GenerateLoadDictionaryElement( | 
|  1320     MacroAssembler* masm) { |  1320     MacroAssembler* masm) { | 
|  1321   // The return address is in ra |  1321   // The return address is in ra | 
|  1322   Label slow, miss; |  1322   Label slow, miss; | 
|  1323  |  1323  | 
|  1324   Register key = LoadIC::NameRegister(); |  1324   Register key = LoadIC::NameRegister(); | 
|  1325   Register receiver = LoadIC::ReceiverRegister(); |  1325   Register receiver = LoadIC::ReceiverRegister(); | 
|  1326   ASSERT(receiver.is(a1)); |  1326   DCHECK(receiver.is(a1)); | 
|  1327   ASSERT(key.is(a2)); |  1327   DCHECK(key.is(a2)); | 
|  1328  |  1328  | 
|  1329   __ UntagAndJumpIfNotSmi(a6, key, &miss); |  1329   __ UntagAndJumpIfNotSmi(a6, key, &miss); | 
|  1330   __ ld(a4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |  1330   __ ld(a4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 
|  1331   ASSERT(kSmiTagSize + kSmiShiftSize == 32); |  1331   DCHECK(kSmiTagSize + kSmiShiftSize == 32); | 
|  1332   __ LoadFromNumberDictionary(&slow, a4, key, v0, a6, a3, a5); |  1332   __ LoadFromNumberDictionary(&slow, a4, key, v0, a6, a3, a5); | 
|  1333   __ Ret(); |  1333   __ Ret(); | 
|  1334  |  1334  | 
|  1335   // Slow case, key and receiver still unmodified. |  1335   // Slow case, key and receiver still unmodified. | 
|  1336   __ bind(&slow); |  1336   __ bind(&slow); | 
|  1337   __ IncrementCounter( |  1337   __ IncrementCounter( | 
|  1338       masm->isolate()->counters()->keyed_load_external_array_slow(), |  1338       masm->isolate()->counters()->keyed_load_external_array_slow(), | 
|  1339       1, a2, a3); |  1339       1, a2, a3); | 
|  1340  |  1340  | 
|  1341   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |  1341   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); | 
|  1342  |  1342  | 
|  1343   // Miss case, call the runtime. |  1343   // Miss case, call the runtime. | 
|  1344   __ bind(&miss); |  1344   __ bind(&miss); | 
|  1345  |  1345  | 
|  1346   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |  1346   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 
|  1347 } |  1347 } | 
|  1348  |  1348  | 
|  1349  |  1349  | 
|  1350 #undef __ |  1350 #undef __ | 
|  1351  |  1351  | 
|  1352 } }  // namespace v8::internal |  1352 } }  // namespace v8::internal | 
|  1353  |  1353  | 
|  1354 #endif  // V8_TARGET_ARCH_MIPS64 |  1354 #endif  // V8_TARGET_ARCH_MIPS64 | 
| OLD | NEW |