| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
| 11 #include "src/stub-cache.h" | 11 #include "src/stub-cache.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 | 15 |
| 16 | 16 |
| 17 #define __ ACCESS_MASM(masm) | 17 #define __ ACCESS_MASM(masm) |
| 18 | 18 |
| 19 | 19 |
| 20 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 20 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
| 21 MacroAssembler* masm, Label* miss_label, Register receiver, | 21 MacroAssembler* masm, Label* miss_label, Register receiver, |
| 22 Handle<Name> name, Register scratch0, Register scratch1) { | 22 Handle<Name> name, Register scratch0, Register scratch1) { |
| 23 ASSERT(!AreAliased(receiver, scratch0, scratch1)); | 23 DCHECK(!AreAliased(receiver, scratch0, scratch1)); |
| 24 ASSERT(name->IsUniqueName()); | 24 DCHECK(name->IsUniqueName()); |
| 25 Counters* counters = masm->isolate()->counters(); | 25 Counters* counters = masm->isolate()->counters(); |
| 26 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 26 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
| 27 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 27 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| 28 | 28 |
| 29 Label done; | 29 Label done; |
| 30 | 30 |
| 31 const int kInterceptorOrAccessCheckNeededMask = | 31 const int kInterceptorOrAccessCheckNeededMask = |
| 32 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 32 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 33 | 33 |
| 34 // Bail out if the receiver has a named interceptor or requires access checks. | 34 // Bail out if the receiver has a named interceptor or requires access checks. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); | 86 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |
| 87 ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); | 87 ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); |
| 88 | 88 |
| 89 uintptr_t key_off_addr = reinterpret_cast<uintptr_t>(key_offset.address()); | 89 uintptr_t key_off_addr = reinterpret_cast<uintptr_t>(key_offset.address()); |
| 90 uintptr_t value_off_addr = | 90 uintptr_t value_off_addr = |
| 91 reinterpret_cast<uintptr_t>(value_offset.address()); | 91 reinterpret_cast<uintptr_t>(value_offset.address()); |
| 92 uintptr_t map_off_addr = reinterpret_cast<uintptr_t>(map_offset.address()); | 92 uintptr_t map_off_addr = reinterpret_cast<uintptr_t>(map_offset.address()); |
| 93 | 93 |
| 94 Label miss; | 94 Label miss; |
| 95 | 95 |
| 96 ASSERT(!AreAliased(name, offset, scratch, scratch2, scratch3)); | 96 DCHECK(!AreAliased(name, offset, scratch, scratch2, scratch3)); |
| 97 | 97 |
| 98 // Multiply by 3 because there are 3 fields per entry. | 98 // Multiply by 3 because there are 3 fields per entry. |
| 99 __ Add(scratch3, offset, Operand(offset, LSL, 1)); | 99 __ Add(scratch3, offset, Operand(offset, LSL, 1)); |
| 100 | 100 |
| 101 // Calculate the base address of the entry. | 101 // Calculate the base address of the entry. |
| 102 __ Mov(scratch, key_offset); | 102 __ Mov(scratch, key_offset); |
| 103 __ Add(scratch, scratch, Operand(scratch3, LSL, kPointerSizeLog2)); | 103 __ Add(scratch, scratch, Operand(scratch3, LSL, kPointerSizeLog2)); |
| 104 | 104 |
| 105 // Check that the key in the entry matches the name. | 105 // Check that the key in the entry matches the name. |
| 106 __ Ldr(scratch2, MemOperand(scratch)); | 106 __ Ldr(scratch2, MemOperand(scratch)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 Register receiver, | 144 Register receiver, |
| 145 Register name, | 145 Register name, |
| 146 Register scratch, | 146 Register scratch, |
| 147 Register extra, | 147 Register extra, |
| 148 Register extra2, | 148 Register extra2, |
| 149 Register extra3) { | 149 Register extra3) { |
| 150 Isolate* isolate = masm->isolate(); | 150 Isolate* isolate = masm->isolate(); |
| 151 Label miss; | 151 Label miss; |
| 152 | 152 |
| 153 // Make sure the flags does not name a specific type. | 153 // Make sure the flags does not name a specific type. |
| 154 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 154 DCHECK(Code::ExtractTypeFromFlags(flags) == 0); |
| 155 | 155 |
| 156 // Make sure that there are no register conflicts. | 156 // Make sure that there are no register conflicts. |
| 157 ASSERT(!AreAliased(receiver, name, scratch, extra, extra2, extra3)); | 157 DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3)); |
| 158 | 158 |
| 159 // Make sure extra and extra2 registers are valid. | 159 // Make sure extra and extra2 registers are valid. |
| 160 ASSERT(!extra.is(no_reg)); | 160 DCHECK(!extra.is(no_reg)); |
| 161 ASSERT(!extra2.is(no_reg)); | 161 DCHECK(!extra2.is(no_reg)); |
| 162 ASSERT(!extra3.is(no_reg)); | 162 DCHECK(!extra3.is(no_reg)); |
| 163 | 163 |
| 164 Counters* counters = masm->isolate()->counters(); | 164 Counters* counters = masm->isolate()->counters(); |
| 165 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, | 165 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, |
| 166 extra2, extra3); | 166 extra2, extra3); |
| 167 | 167 |
| 168 // Check that the receiver isn't a smi. | 168 // Check that the receiver isn't a smi. |
| 169 __ JumpIfSmi(receiver, &miss); | 169 __ JumpIfSmi(receiver, &miss); |
| 170 | 170 |
| 171 // Compute the hash for primary table. | 171 // Compute the hash for primary table. |
| 172 __ Ldr(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); | 172 __ Ldr(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 } | 233 } |
| 234 | 234 |
| 235 | 235 |
| 236 // Generate code to check that a global property cell is empty. Create | 236 // Generate code to check that a global property cell is empty. Create |
| 237 // the property cell at compilation time if no cell exists for the | 237 // the property cell at compilation time if no cell exists for the |
| 238 // property. | 238 // property. |
| 239 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 239 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
| 240 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 240 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
| 241 Register scratch, Label* miss) { | 241 Register scratch, Label* miss) { |
| 242 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 242 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
| 243 ASSERT(cell->value()->IsTheHole()); | 243 DCHECK(cell->value()->IsTheHole()); |
| 244 __ Mov(scratch, Operand(cell)); | 244 __ Mov(scratch, Operand(cell)); |
| 245 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 245 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
| 246 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); | 246 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); |
| 247 } | 247 } |
| 248 | 248 |
| 249 | 249 |
| 250 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, | 250 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, |
| 251 Register holder, Register name, | 251 Register holder, Register name, |
| 252 Handle<JSObject> holder_obj) { | 252 Handle<JSObject> holder_obj) { |
| 253 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 253 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); |
| 254 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); | 254 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); |
| 255 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); | 255 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); |
| 256 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); | 256 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); |
| 257 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); | 257 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); |
| 258 | 258 |
| 259 __ Push(name); | 259 __ Push(name); |
| 260 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 260 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
| 261 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 261 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
| 262 Register scratch = name; | 262 Register scratch = name; |
| 263 __ Mov(scratch, Operand(interceptor)); | 263 __ Mov(scratch, Operand(interceptor)); |
| 264 __ Push(scratch, receiver, holder); | 264 __ Push(scratch, receiver, holder); |
| 265 } | 265 } |
| 266 | 266 |
| 267 | 267 |
| 268 static void CompileCallLoadPropertyWithInterceptor( | 268 static void CompileCallLoadPropertyWithInterceptor( |
| 269 MacroAssembler* masm, Register receiver, Register holder, Register name, | 269 MacroAssembler* masm, Register receiver, Register holder, Register name, |
| 270 Handle<JSObject> holder_obj, IC::UtilityId id) { | 270 Handle<JSObject> holder_obj, IC::UtilityId id) { |
| 271 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 271 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 272 | 272 |
| 273 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), | 273 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), |
| 274 NamedLoadHandlerCompiler::kInterceptorArgsLength); | 274 NamedLoadHandlerCompiler::kInterceptorArgsLength); |
| 275 } | 275 } |
| 276 | 276 |
| 277 | 277 |
| 278 // Generate call to api function. | 278 // Generate call to api function. |
| 279 void PropertyHandlerCompiler::GenerateFastApiCall( | 279 void PropertyHandlerCompiler::GenerateFastApiCall( |
| 280 MacroAssembler* masm, const CallOptimization& optimization, | 280 MacroAssembler* masm, const CallOptimization& optimization, |
| 281 Handle<Map> receiver_map, Register receiver, Register scratch, | 281 Handle<Map> receiver_map, Register receiver, Register scratch, |
| 282 bool is_store, int argc, Register* values) { | 282 bool is_store, int argc, Register* values) { |
| 283 ASSERT(!AreAliased(receiver, scratch)); | 283 DCHECK(!AreAliased(receiver, scratch)); |
| 284 | 284 |
| 285 MacroAssembler::PushPopQueue queue(masm); | 285 MacroAssembler::PushPopQueue queue(masm); |
| 286 queue.Queue(receiver); | 286 queue.Queue(receiver); |
| 287 // Write the arguments to the stack frame. | 287 // Write the arguments to the stack frame. |
| 288 for (int i = 0; i < argc; i++) { | 288 for (int i = 0; i < argc; i++) { |
| 289 Register arg = values[argc - 1 - i]; | 289 Register arg = values[argc - 1 - i]; |
| 290 ASSERT(!AreAliased(receiver, scratch, arg)); | 290 DCHECK(!AreAliased(receiver, scratch, arg)); |
| 291 queue.Queue(arg); | 291 queue.Queue(arg); |
| 292 } | 292 } |
| 293 queue.PushQueued(); | 293 queue.PushQueued(); |
| 294 | 294 |
| 295 ASSERT(optimization.is_simple_api_call()); | 295 DCHECK(optimization.is_simple_api_call()); |
| 296 | 296 |
| 297 // Abi for CallApiFunctionStub. | 297 // Abi for CallApiFunctionStub. |
| 298 Register callee = x0; | 298 Register callee = x0; |
| 299 Register call_data = x4; | 299 Register call_data = x4; |
| 300 Register holder = x2; | 300 Register holder = x2; |
| 301 Register api_function_address = x1; | 301 Register api_function_address = x1; |
| 302 | 302 |
| 303 // Put holder in place. | 303 // Put holder in place. |
| 304 CallOptimization::HolderLookup holder_lookup; | 304 CallOptimization::HolderLookup holder_lookup; |
| 305 Handle<JSObject> api_holder = | 305 Handle<JSObject> api_holder = |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 // Generate StoreTransition code, value is passed in x0 register. | 371 // Generate StoreTransition code, value is passed in x0 register. |
| 372 // When leaving generated code after success, the receiver_reg and storage_reg | 372 // When leaving generated code after success, the receiver_reg and storage_reg |
| 373 // may be clobbered. Upon branch to miss_label, the receiver and name registers | 373 // may be clobbered. Upon branch to miss_label, the receiver and name registers |
| 374 // have their original values. | 374 // have their original values. |
| 375 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 375 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
| 376 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 376 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
| 377 Register storage_reg, Register value_reg, Register scratch1, | 377 Register storage_reg, Register value_reg, Register scratch1, |
| 378 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { | 378 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { |
| 379 Label exit; | 379 Label exit; |
| 380 | 380 |
| 381 ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg, | 381 DCHECK(!AreAliased(receiver_reg, storage_reg, value_reg, |
| 382 scratch1, scratch2, scratch3)); | 382 scratch1, scratch2, scratch3)); |
| 383 | 383 |
| 384 // We don't need scratch3. | 384 // We don't need scratch3. |
| 385 scratch3 = NoReg; | 385 scratch3 = NoReg; |
| 386 | 386 |
| 387 int descriptor = transition->LastAdded(); | 387 int descriptor = transition->LastAdded(); |
| 388 DescriptorArray* descriptors = transition->instance_descriptors(); | 388 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 389 PropertyDetails details = descriptors->GetDetails(descriptor); | 389 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 390 Representation representation = details.representation(); | 390 Representation representation = details.representation(); |
| 391 ASSERT(!representation.IsNone()); | 391 DCHECK(!representation.IsNone()); |
| 392 | 392 |
| 393 if (details.type() == CONSTANT) { | 393 if (details.type() == CONSTANT) { |
| 394 Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); | 394 Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); |
| 395 __ LoadObject(scratch1, constant); | 395 __ LoadObject(scratch1, constant); |
| 396 __ Cmp(value_reg, scratch1); | 396 __ Cmp(value_reg, scratch1); |
| 397 __ B(ne, miss_label); | 397 __ B(ne, miss_label); |
| 398 } else if (representation.IsSmi()) { | 398 } else if (representation.IsSmi()) { |
| 399 __ JumpIfNotSmi(value_reg, miss_label); | 399 __ JumpIfNotSmi(value_reg, miss_label); |
| 400 } else if (representation.IsHeapObject()) { | 400 } else if (representation.IsHeapObject()) { |
| 401 __ JumpIfSmi(value_reg, miss_label); | 401 __ JumpIfSmi(value_reg, miss_label); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 426 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, | 426 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
| 427 miss_label, DONT_DO_SMI_CHECK); | 427 miss_label, DONT_DO_SMI_CHECK); |
| 428 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 428 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
| 429 | 429 |
| 430 __ Bind(&do_store); | 430 __ Bind(&do_store); |
| 431 __ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2, temp_double, | 431 __ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2, temp_double, |
| 432 NoReg, MUTABLE); | 432 NoReg, MUTABLE); |
| 433 } | 433 } |
| 434 | 434 |
| 435 // Stub never generated for objects that require access checks. | 435 // Stub never generated for objects that require access checks. |
| 436 ASSERT(!transition->is_access_check_needed()); | 436 DCHECK(!transition->is_access_check_needed()); |
| 437 | 437 |
| 438 // Perform map transition for the receiver if necessary. | 438 // Perform map transition for the receiver if necessary. |
| 439 if (details.type() == FIELD && | 439 if (details.type() == FIELD && |
| 440 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 440 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
| 441 // The properties must be extended before we can store the value. | 441 // The properties must be extended before we can store the value. |
| 442 // We jump to a runtime call that extends the properties array. | 442 // We jump to a runtime call that extends the properties array. |
| 443 __ Mov(scratch1, Operand(transition)); | 443 __ Mov(scratch1, Operand(transition)); |
| 444 __ Push(receiver_reg, scratch1, value_reg); | 444 __ Push(receiver_reg, scratch1, value_reg); |
| 445 __ TailCallExternalReference( | 445 __ TailCallExternalReference( |
| 446 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 446 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 457 __ RecordWriteField(receiver_reg, | 457 __ RecordWriteField(receiver_reg, |
| 458 HeapObject::kMapOffset, | 458 HeapObject::kMapOffset, |
| 459 scratch1, | 459 scratch1, |
| 460 scratch2, | 460 scratch2, |
| 461 kLRHasNotBeenSaved, | 461 kLRHasNotBeenSaved, |
| 462 kDontSaveFPRegs, | 462 kDontSaveFPRegs, |
| 463 OMIT_REMEMBERED_SET, | 463 OMIT_REMEMBERED_SET, |
| 464 OMIT_SMI_CHECK); | 464 OMIT_SMI_CHECK); |
| 465 | 465 |
| 466 if (details.type() == CONSTANT) { | 466 if (details.type() == CONSTANT) { |
| 467 ASSERT(value_reg.is(x0)); | 467 DCHECK(value_reg.is(x0)); |
| 468 __ Ret(); | 468 __ Ret(); |
| 469 return; | 469 return; |
| 470 } | 470 } |
| 471 | 471 |
| 472 int index = transition->instance_descriptors()->GetFieldIndex( | 472 int index = transition->instance_descriptors()->GetFieldIndex( |
| 473 transition->LastAdded()); | 473 transition->LastAdded()); |
| 474 | 474 |
| 475 // Adjust for the number of properties stored in the object. Even in the | 475 // Adjust for the number of properties stored in the object. Even in the |
| 476 // face of a transition we can use the old map here because the size of the | 476 // face of a transition we can use the old map here because the size of the |
| 477 // object and the number of in-object properties is not going to change. | 477 // object and the number of in-object properties is not going to change. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 receiver_reg, | 519 receiver_reg, |
| 520 kLRHasNotBeenSaved, | 520 kLRHasNotBeenSaved, |
| 521 kDontSaveFPRegs, | 521 kDontSaveFPRegs, |
| 522 EMIT_REMEMBERED_SET, | 522 EMIT_REMEMBERED_SET, |
| 523 smi_check); | 523 smi_check); |
| 524 } | 524 } |
| 525 } | 525 } |
| 526 | 526 |
| 527 __ Bind(&exit); | 527 __ Bind(&exit); |
| 528 // Return the value (register x0). | 528 // Return the value (register x0). |
| 529 ASSERT(value_reg.is(x0)); | 529 DCHECK(value_reg.is(x0)); |
| 530 __ Ret(); | 530 __ Ret(); |
| 531 } | 531 } |
| 532 | 532 |
| 533 | 533 |
| 534 // Generate StoreField code, value is passed in x0 register. | 534 // Generate StoreField code, value is passed in x0 register. |
| 535 // When leaving generated code after success, the receiver_reg and name_reg may | 535 // When leaving generated code after success, the receiver_reg and name_reg may |
| 536 // be clobbered. Upon branch to miss_label, the receiver and name registers have | 536 // be clobbered. Upon branch to miss_label, the receiver and name registers have |
| 537 // their original values. | 537 // their original values. |
| 538 void NamedStoreHandlerCompiler::GenerateStoreField( | 538 void NamedStoreHandlerCompiler::GenerateStoreField( |
| 539 Handle<JSObject> object, LookupResult* lookup, Register receiver_reg, | 539 Handle<JSObject> object, LookupResult* lookup, Register receiver_reg, |
| 540 Register name_reg, Register value_reg, Register scratch1, Register scratch2, | 540 Register name_reg, Register value_reg, Register scratch1, Register scratch2, |
| 541 Label* miss_label) { | 541 Label* miss_label) { |
| 542 // x0 : value | 542 // x0 : value |
| 543 Label exit; | 543 Label exit; |
| 544 | 544 |
| 545 // Stub never generated for objects that require access checks. | 545 // Stub never generated for objects that require access checks. |
| 546 ASSERT(!object->IsAccessCheckNeeded()); | 546 DCHECK(!object->IsAccessCheckNeeded()); |
| 547 ASSERT(!object->IsJSGlobalProxy()); | 547 DCHECK(!object->IsJSGlobalProxy()); |
| 548 | 548 |
| 549 FieldIndex index = lookup->GetFieldIndex(); | 549 FieldIndex index = lookup->GetFieldIndex(); |
| 550 | 550 |
| 551 Representation representation = lookup->representation(); | 551 Representation representation = lookup->representation(); |
| 552 ASSERT(!representation.IsNone()); | 552 DCHECK(!representation.IsNone()); |
| 553 if (representation.IsSmi()) { | 553 if (representation.IsSmi()) { |
| 554 __ JumpIfNotSmi(value_reg, miss_label); | 554 __ JumpIfNotSmi(value_reg, miss_label); |
| 555 } else if (representation.IsHeapObject()) { | 555 } else if (representation.IsHeapObject()) { |
| 556 __ JumpIfSmi(value_reg, miss_label); | 556 __ JumpIfSmi(value_reg, miss_label); |
| 557 HeapType* field_type = lookup->GetFieldType(); | 557 HeapType* field_type = lookup->GetFieldType(); |
| 558 HeapType::Iterator<Map> it = field_type->Classes(); | 558 HeapType::Iterator<Map> it = field_type->Classes(); |
| 559 if (!it.Done()) { | 559 if (!it.Done()) { |
| 560 __ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 560 __ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
| 561 Label do_store; | 561 Label do_store; |
| 562 while (true) { | 562 while (true) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 591 __ JumpIfSmi(value_reg, &do_store); | 591 __ JumpIfSmi(value_reg, &do_store); |
| 592 | 592 |
| 593 __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, | 593 __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, |
| 594 miss_label, DONT_DO_SMI_CHECK); | 594 miss_label, DONT_DO_SMI_CHECK); |
| 595 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 595 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
| 596 | 596 |
| 597 __ Bind(&do_store); | 597 __ Bind(&do_store); |
| 598 __ Str(temp_double, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); | 598 __ Str(temp_double, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); |
| 599 | 599 |
| 600 // Return the value (register x0). | 600 // Return the value (register x0). |
| 601 ASSERT(value_reg.is(x0)); | 601 DCHECK(value_reg.is(x0)); |
| 602 __ Ret(); | 602 __ Ret(); |
| 603 return; | 603 return; |
| 604 } | 604 } |
| 605 | 605 |
| 606 // TODO(verwaest): Share this code as a code stub. | 606 // TODO(verwaest): Share this code as a code stub. |
| 607 SmiCheck smi_check = representation.IsTagged() | 607 SmiCheck smi_check = representation.IsTagged() |
| 608 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 608 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
| 609 if (index.is_inobject()) { | 609 if (index.is_inobject()) { |
| 610 // Set the property straight into the object. | 610 // Set the property straight into the object. |
| 611 __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset())); | 611 __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset())); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 receiver_reg, | 646 receiver_reg, |
| 647 kLRHasNotBeenSaved, | 647 kLRHasNotBeenSaved, |
| 648 kDontSaveFPRegs, | 648 kDontSaveFPRegs, |
| 649 EMIT_REMEMBERED_SET, | 649 EMIT_REMEMBERED_SET, |
| 650 smi_check); | 650 smi_check); |
| 651 } | 651 } |
| 652 } | 652 } |
| 653 | 653 |
| 654 __ Bind(&exit); | 654 __ Bind(&exit); |
| 655 // Return the value (register x0). | 655 // Return the value (register x0). |
| 656 ASSERT(value_reg.is(x0)); | 656 DCHECK(value_reg.is(x0)); |
| 657 __ Ret(); | 657 __ Ret(); |
| 658 } | 658 } |
| 659 | 659 |
| 660 | 660 |
| 661 Register PropertyHandlerCompiler::CheckPrototypes( | 661 Register PropertyHandlerCompiler::CheckPrototypes( |
| 662 Register object_reg, Register holder_reg, Register scratch1, | 662 Register object_reg, Register holder_reg, Register scratch1, |
| 663 Register scratch2, Handle<Name> name, Label* miss, | 663 Register scratch2, Handle<Name> name, Label* miss, |
| 664 PrototypeCheckType check) { | 664 PrototypeCheckType check) { |
| 665 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 665 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
| 666 | 666 |
| 667 // object_reg and holder_reg registers can alias. | 667 // object_reg and holder_reg registers can alias. |
| 668 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); | 668 DCHECK(!AreAliased(object_reg, scratch1, scratch2)); |
| 669 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); | 669 DCHECK(!AreAliased(holder_reg, scratch1, scratch2)); |
| 670 | 670 |
| 671 // Keep track of the current object in register reg. | 671 // Keep track of the current object in register reg. |
| 672 Register reg = object_reg; | 672 Register reg = object_reg; |
| 673 int depth = 0; | 673 int depth = 0; |
| 674 | 674 |
| 675 Handle<JSObject> current = Handle<JSObject>::null(); | 675 Handle<JSObject> current = Handle<JSObject>::null(); |
| 676 if (type()->IsConstant()) { | 676 if (type()->IsConstant()) { |
| 677 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 677 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
| 678 } | 678 } |
| 679 Handle<JSObject> prototype = Handle<JSObject>::null(); | 679 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 680 Handle<Map> current_map = receiver_map; | 680 Handle<Map> current_map = receiver_map; |
| 681 Handle<Map> holder_map(holder()->map()); | 681 Handle<Map> holder_map(holder()->map()); |
| 682 // Traverse the prototype chain and check the maps in the prototype chain for | 682 // Traverse the prototype chain and check the maps in the prototype chain for |
| 683 // fast and global objects or do negative lookup for normal objects. | 683 // fast and global objects or do negative lookup for normal objects. |
| 684 while (!current_map.is_identical_to(holder_map)) { | 684 while (!current_map.is_identical_to(holder_map)) { |
| 685 ++depth; | 685 ++depth; |
| 686 | 686 |
| 687 // Only global objects and objects that do not require access | 687 // Only global objects and objects that do not require access |
| 688 // checks are allowed in stubs. | 688 // checks are allowed in stubs. |
| 689 ASSERT(current_map->IsJSGlobalProxyMap() || | 689 DCHECK(current_map->IsJSGlobalProxyMap() || |
| 690 !current_map->is_access_check_needed()); | 690 !current_map->is_access_check_needed()); |
| 691 | 691 |
| 692 prototype = handle(JSObject::cast(current_map->prototype())); | 692 prototype = handle(JSObject::cast(current_map->prototype())); |
| 693 if (current_map->is_dictionary_map() && | 693 if (current_map->is_dictionary_map() && |
| 694 !current_map->IsJSGlobalObjectMap() && | 694 !current_map->IsJSGlobalObjectMap() && |
| 695 !current_map->IsJSGlobalProxyMap()) { | 695 !current_map->IsJSGlobalProxyMap()) { |
| 696 if (!name->IsUniqueName()) { | 696 if (!name->IsUniqueName()) { |
| 697 ASSERT(name->IsString()); | 697 DCHECK(name->IsString()); |
| 698 name = factory()->InternalizeString(Handle<String>::cast(name)); | 698 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 699 } | 699 } |
| 700 ASSERT(current.is_null() || | 700 DCHECK(current.is_null() || |
| 701 (current->property_dictionary()->FindEntry(name) == | 701 (current->property_dictionary()->FindEntry(name) == |
| 702 NameDictionary::kNotFound)); | 702 NameDictionary::kNotFound)); |
| 703 | 703 |
| 704 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 704 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 705 scratch1, scratch2); | 705 scratch1, scratch2); |
| 706 | 706 |
| 707 __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 707 __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 708 reg = holder_reg; // From now on the object will be in holder_reg. | 708 reg = holder_reg; // From now on the object will be in holder_reg. |
| 709 __ Ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 709 __ Ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
| 710 } else { | 710 } else { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 // Log the check depth. | 750 // Log the check depth. |
| 751 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 751 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 752 | 752 |
| 753 // Check the holder map. | 753 // Check the holder map. |
| 754 if (depth != 0 || check == CHECK_ALL_MAPS) { | 754 if (depth != 0 || check == CHECK_ALL_MAPS) { |
| 755 // Check the holder map. | 755 // Check the holder map. |
| 756 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); | 756 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); |
| 757 } | 757 } |
| 758 | 758 |
| 759 // Perform security check for access to the global object. | 759 // Perform security check for access to the global object. |
| 760 ASSERT(current_map->IsJSGlobalProxyMap() || | 760 DCHECK(current_map->IsJSGlobalProxyMap() || |
| 761 !current_map->is_access_check_needed()); | 761 !current_map->is_access_check_needed()); |
| 762 if (current_map->IsJSGlobalProxyMap()) { | 762 if (current_map->IsJSGlobalProxyMap()) { |
| 763 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 763 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
| 764 } | 764 } |
| 765 | 765 |
| 766 // Return the register containing the holder. | 766 // Return the register containing the holder. |
| 767 return reg; | 767 return reg; |
| 768 } | 768 } |
| 769 | 769 |
| 770 | 770 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 798 Handle<Name> name, | 798 Handle<Name> name, |
| 799 Handle<Object> callback) { | 799 Handle<Object> callback) { |
| 800 Label miss; | 800 Label miss; |
| 801 | 801 |
| 802 Register reg = FrontendHeader(object_reg, name, &miss); | 802 Register reg = FrontendHeader(object_reg, name, &miss); |
| 803 // FrontendHeader can return its result into scratch1() so do not | 803 // FrontendHeader can return its result into scratch1() so do not |
| 804 // use it. | 804 // use it. |
| 805 Register scratch2 = this->scratch2(); | 805 Register scratch2 = this->scratch2(); |
| 806 Register scratch3 = this->scratch3(); | 806 Register scratch3 = this->scratch3(); |
| 807 Register dictionary = this->scratch4(); | 807 Register dictionary = this->scratch4(); |
| 808 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); | 808 DCHECK(!AreAliased(reg, scratch2, scratch3, dictionary)); |
| 809 | 809 |
| 810 if (!holder()->HasFastProperties()) { | 810 if (!holder()->HasFastProperties()) { |
| 811 ASSERT(!holder()->IsGlobalObject()); | 811 DCHECK(!holder()->IsGlobalObject()); |
| 812 // Load the properties dictionary. | 812 // Load the properties dictionary. |
| 813 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 813 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
| 814 | 814 |
| 815 // Probe the dictionary. | 815 // Probe the dictionary. |
| 816 Label probe_done; | 816 Label probe_done; |
| 817 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), | 817 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), |
| 818 &miss, | 818 &miss, |
| 819 &probe_done, | 819 &probe_done, |
| 820 dictionary, | 820 dictionary, |
| 821 this->name(), | 821 this->name(), |
| (...skipping 27 matching lines...) Expand all Loading... |
| 849 | 849 |
| 850 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 850 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 851 // Return the constant value. | 851 // Return the constant value. |
| 852 __ LoadObject(x0, value); | 852 __ LoadObject(x0, value); |
| 853 __ Ret(); | 853 __ Ret(); |
| 854 } | 854 } |
| 855 | 855 |
| 856 | 856 |
| 857 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 857 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
| 858 Register reg, Handle<ExecutableAccessorInfo> callback) { | 858 Register reg, Handle<ExecutableAccessorInfo> callback) { |
| 859 ASSERT(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); | 859 DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); |
| 860 | 860 |
| 861 // Build ExecutableAccessorInfo::args_ list on the stack and push property | 861 // Build ExecutableAccessorInfo::args_ list on the stack and push property |
| 862 // name below the exit frame to make GC aware of them and store pointers to | 862 // name below the exit frame to make GC aware of them and store pointers to |
| 863 // them. | 863 // them. |
| 864 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 864 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
| 865 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 865 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
| 866 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 866 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
| 867 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 867 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
| 868 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 868 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
| 869 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 869 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 __ Mov(getter_address_reg, ref); | 904 __ Mov(getter_address_reg, ref); |
| 905 | 905 |
| 906 CallApiGetterStub stub(isolate()); | 906 CallApiGetterStub stub(isolate()); |
| 907 __ TailCallStub(&stub); | 907 __ TailCallStub(&stub); |
| 908 } | 908 } |
| 909 | 909 |
| 910 | 910 |
| 911 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, | 911 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
| 912 LookupResult* lookup, | 912 LookupResult* lookup, |
| 913 Handle<Name> name) { | 913 Handle<Name> name) { |
| 914 ASSERT(!AreAliased(receiver(), this->name(), | 914 DCHECK(!AreAliased(receiver(), this->name(), |
| 915 scratch1(), scratch2(), scratch3())); | 915 scratch1(), scratch2(), scratch3())); |
| 916 ASSERT(holder()->HasNamedInterceptor()); | 916 DCHECK(holder()->HasNamedInterceptor()); |
| 917 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); | 917 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
| 918 | 918 |
| 919 // So far the most popular follow ups for interceptor loads are FIELD | 919 // So far the most popular follow ups for interceptor loads are FIELD |
| 920 // and CALLBACKS, so inline only them, other cases may be added later. | 920 // and CALLBACKS, so inline only them, other cases may be added later. |
| 921 bool compile_followup_inline = false; | 921 bool compile_followup_inline = false; |
| 922 if (lookup->IsFound() && lookup->IsCacheable()) { | 922 if (lookup->IsFound() && lookup->IsCacheable()) { |
| 923 if (lookup->IsField()) { | 923 if (lookup->IsField()) { |
| 924 compile_followup_inline = true; | 924 compile_followup_inline = true; |
| 925 } else if (lookup->type() == CALLBACKS && | 925 } else if (lookup->type() == CALLBACKS && |
| 926 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 926 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
| 927 Handle<ExecutableAccessorInfo> callback( | 927 Handle<ExecutableAccessorInfo> callback( |
| 928 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 928 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
| 929 compile_followup_inline = | 929 compile_followup_inline = |
| 930 callback->getter() != NULL && | 930 callback->getter() != NULL && |
| 931 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 931 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
| 932 type()); | 932 type()); |
| 933 } | 933 } |
| 934 } | 934 } |
| 935 | 935 |
| 936 if (compile_followup_inline) { | 936 if (compile_followup_inline) { |
| 937 // Compile the interceptor call, followed by inline code to load the | 937 // Compile the interceptor call, followed by inline code to load the |
| 938 // property from further up the prototype chain if the call fails. | 938 // property from further up the prototype chain if the call fails. |
| 939 // Check that the maps haven't changed. | 939 // Check that the maps haven't changed. |
| 940 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 940 DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
| 941 | 941 |
| 942 // Preserve the receiver register explicitly whenever it is different from | 942 // Preserve the receiver register explicitly whenever it is different from |
| 943 // the holder and it is needed should the interceptor return without any | 943 // the holder and it is needed should the interceptor return without any |
| 944 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 944 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
| 945 // the FIELD case might cause a miss during the prototype check. | 945 // the FIELD case might cause a miss during the prototype check. |
| 946 bool must_perfrom_prototype_check = *holder() != lookup->holder(); | 946 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
| 947 bool must_preserve_receiver_reg = !receiver().Is(holder_reg) && | 947 bool must_preserve_receiver_reg = !receiver().Is(holder_reg) && |
| 948 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 948 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
| 949 | 949 |
| 950 // Save necessary data before invoking an interceptor. | 950 // Save necessary data before invoking an interceptor. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 996 } | 996 } |
| 997 | 997 |
| 998 | 998 |
| 999 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 999 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 1000 Handle<JSObject> object, Handle<Name> name, | 1000 Handle<JSObject> object, Handle<Name> name, |
| 1001 Handle<ExecutableAccessorInfo> callback) { | 1001 Handle<ExecutableAccessorInfo> callback) { |
| 1002 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); | 1002 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); |
| 1003 Register holder_reg = Frontend(receiver(), name); | 1003 Register holder_reg = Frontend(receiver(), name); |
| 1004 | 1004 |
| 1005 // Stub never generated for non-global objects that require access checks. | 1005 // Stub never generated for non-global objects that require access checks. |
| 1006 ASSERT(holder()->IsJSGlobalProxy() || !holder()->IsAccessCheckNeeded()); | 1006 DCHECK(holder()->IsJSGlobalProxy() || !holder()->IsAccessCheckNeeded()); |
| 1007 | 1007 |
| 1008 // receiver() and holder_reg can alias. | 1008 // receiver() and holder_reg can alias. |
| 1009 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); | 1009 DCHECK(!AreAliased(receiver(), scratch1(), scratch2(), value())); |
| 1010 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); | 1010 DCHECK(!AreAliased(holder_reg, scratch1(), scratch2(), value())); |
| 1011 __ Mov(scratch1(), Operand(callback)); | 1011 __ Mov(scratch1(), Operand(callback)); |
| 1012 __ Mov(scratch2(), Operand(name)); | 1012 __ Mov(scratch2(), Operand(name)); |
| 1013 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); | 1013 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); |
| 1014 | 1014 |
| 1015 // Do tail-call to the runtime system. | 1015 // Do tail-call to the runtime system. |
| 1016 ExternalReference store_callback_property = | 1016 ExternalReference store_callback_property = |
| 1017 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1017 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 1018 __ TailCallExternalReference(store_callback_property, 5, 1); | 1018 __ TailCallExternalReference(store_callback_property, 5, 1); |
| 1019 | 1019 |
| 1020 // Return the generated code. | 1020 // Return the generated code. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1103 Register name = LoadIC::NameRegister(); | 1103 Register name = LoadIC::NameRegister(); |
| 1104 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; | 1104 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; |
| 1105 return registers; | 1105 return registers; |
| 1106 } | 1106 } |
| 1107 | 1107 |
| 1108 | 1108 |
| 1109 Register* PropertyAccessCompiler::store_calling_convention() { | 1109 Register* PropertyAccessCompiler::store_calling_convention() { |
| 1110 // receiver, value, scratch1, scratch2, scratch3. | 1110 // receiver, value, scratch1, scratch2, scratch3. |
| 1111 Register receiver = StoreIC::ReceiverRegister(); | 1111 Register receiver = StoreIC::ReceiverRegister(); |
| 1112 Register name = StoreIC::NameRegister(); | 1112 Register name = StoreIC::NameRegister(); |
| 1113 ASSERT(x3.is(KeyedStoreIC::MapRegister())); | 1113 DCHECK(x3.is(KeyedStoreIC::MapRegister())); |
| 1114 static Register registers[] = { receiver, name, x3, x4, x5 }; | 1114 static Register registers[] = { receiver, name, x3, x4, x5 }; |
| 1115 return registers; | 1115 return registers; |
| 1116 } | 1116 } |
| 1117 | 1117 |
| 1118 | 1118 |
| 1119 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 1119 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1120 | 1120 |
| 1121 | 1121 |
| 1122 #undef __ | 1122 #undef __ |
| 1123 #define __ ACCESS_MASM(masm) | 1123 #define __ ACCESS_MASM(masm) |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 __ CompareAndBranch(this->name(), Operand(name), ne, &miss); | 1200 __ CompareAndBranch(this->name(), Operand(name), ne, &miss); |
| 1201 } | 1201 } |
| 1202 } | 1202 } |
| 1203 | 1203 |
| 1204 Label number_case; | 1204 Label number_case; |
| 1205 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1205 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
| 1206 __ JumpIfSmi(receiver(), smi_target); | 1206 __ JumpIfSmi(receiver(), smi_target); |
| 1207 | 1207 |
| 1208 // Polymorphic keyed stores may use the map register | 1208 // Polymorphic keyed stores may use the map register |
| 1209 Register map_reg = scratch1(); | 1209 Register map_reg = scratch1(); |
| 1210 ASSERT(kind() != Code::KEYED_STORE_IC || | 1210 DCHECK(kind() != Code::KEYED_STORE_IC || |
| 1211 map_reg.is(KeyedStoreIC::MapRegister())); | 1211 map_reg.is(KeyedStoreIC::MapRegister())); |
| 1212 __ Ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 1212 __ Ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
| 1213 int receiver_count = types->length(); | 1213 int receiver_count = types->length(); |
| 1214 int number_of_handled_maps = 0; | 1214 int number_of_handled_maps = 0; |
| 1215 for (int current = 0; current < receiver_count; ++current) { | 1215 for (int current = 0; current < receiver_count; ++current) { |
| 1216 Handle<HeapType> type = types->at(current); | 1216 Handle<HeapType> type = types->at(current); |
| 1217 Handle<Map> map = IC::TypeToMap(*type, isolate()); | 1217 Handle<Map> map = IC::TypeToMap(*type, isolate()); |
| 1218 if (!map->is_deprecated()) { | 1218 if (!map->is_deprecated()) { |
| 1219 number_of_handled_maps++; | 1219 number_of_handled_maps++; |
| 1220 Label try_next; | 1220 Label try_next; |
| 1221 __ Cmp(map_reg, Operand(map)); | 1221 __ Cmp(map_reg, Operand(map)); |
| 1222 __ B(ne, &try_next); | 1222 __ B(ne, &try_next); |
| 1223 if (type->Is(HeapType::Number())) { | 1223 if (type->Is(HeapType::Number())) { |
| 1224 ASSERT(!number_case.is_unused()); | 1224 DCHECK(!number_case.is_unused()); |
| 1225 __ Bind(&number_case); | 1225 __ Bind(&number_case); |
| 1226 } | 1226 } |
| 1227 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET); | 1227 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET); |
| 1228 __ Bind(&try_next); | 1228 __ Bind(&try_next); |
| 1229 } | 1229 } |
| 1230 } | 1230 } |
| 1231 ASSERT(number_of_handled_maps != 0); | 1231 DCHECK(number_of_handled_maps != 0); |
| 1232 | 1232 |
| 1233 __ Bind(&miss); | 1233 __ Bind(&miss); |
| 1234 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1234 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1235 | 1235 |
| 1236 // Return the generated code. | 1236 // Return the generated code. |
| 1237 InlineCacheState state = | 1237 InlineCacheState state = |
| 1238 (number_of_handled_maps > 1) ? POLYMORPHIC : MONOMORPHIC; | 1238 (number_of_handled_maps > 1) ? POLYMORPHIC : MONOMORPHIC; |
| 1239 return GetCode(kind(), type, name, state); | 1239 return GetCode(kind(), type, name, state); |
| 1240 } | 1240 } |
| 1241 | 1241 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1276 #define __ ACCESS_MASM(masm) | 1276 #define __ ACCESS_MASM(masm) |
| 1277 | 1277 |
| 1278 void ElementHandlerCompiler::GenerateLoadDictionaryElement( | 1278 void ElementHandlerCompiler::GenerateLoadDictionaryElement( |
| 1279 MacroAssembler* masm) { | 1279 MacroAssembler* masm) { |
| 1280 // The return address is in lr. | 1280 // The return address is in lr. |
| 1281 Label slow, miss; | 1281 Label slow, miss; |
| 1282 | 1282 |
| 1283 Register result = x0; | 1283 Register result = x0; |
| 1284 Register key = LoadIC::NameRegister(); | 1284 Register key = LoadIC::NameRegister(); |
| 1285 Register receiver = LoadIC::ReceiverRegister(); | 1285 Register receiver = LoadIC::ReceiverRegister(); |
| 1286 ASSERT(receiver.is(x1)); | 1286 DCHECK(receiver.is(x1)); |
| 1287 ASSERT(key.is(x2)); | 1287 DCHECK(key.is(x2)); |
| 1288 | 1288 |
| 1289 __ JumpIfNotSmi(key, &miss); | 1289 __ JumpIfNotSmi(key, &miss); |
| 1290 __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 1290 __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 1291 __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6); | 1291 __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6); |
| 1292 __ Ret(); | 1292 __ Ret(); |
| 1293 | 1293 |
| 1294 __ Bind(&slow); | 1294 __ Bind(&slow); |
| 1295 __ IncrementCounter( | 1295 __ IncrementCounter( |
| 1296 masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3); | 1296 masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3); |
| 1297 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); | 1297 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
| 1298 | 1298 |
| 1299 // Miss case, call the runtime. | 1299 // Miss case, call the runtime. |
| 1300 __ Bind(&miss); | 1300 __ Bind(&miss); |
| 1301 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1301 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1302 } | 1302 } |
| 1303 | 1303 |
| 1304 | 1304 |
| 1305 } } // namespace v8::internal | 1305 } } // namespace v8::internal |
| 1306 | 1306 |
| 1307 #endif // V8_TARGET_ARCH_ARM64 | 1307 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |