| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 6 | 6 |
| 7 #include "src/ic/handler-compiler.h" | 7 #include "src/ic/handler-compiler.h" |
| 8 | 8 |
| 9 #include "src/api-arguments.h" | 9 #include "src/api-arguments.h" |
| 10 #include "src/field-type.h" | 10 #include "src/field-type.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 __ Pop(slot); | 37 __ Pop(slot); |
| 38 } | 38 } |
| 39 | 39 |
| 40 | 40 |
| 41 void PropertyHandlerCompiler::DiscardVectorAndSlot() { | 41 void PropertyHandlerCompiler::DiscardVectorAndSlot() { |
| 42 MacroAssembler* masm = this->masm(); | 42 MacroAssembler* masm = this->masm(); |
| 43 // Remove vector and slot. | 43 // Remove vector and slot. |
| 44 __ Drop(2); | 44 __ Drop(2); |
| 45 } | 45 } |
| 46 | 46 |
| 47 void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { | |
| 48 // No-op. Return address is in lr register. | |
| 49 } | |
| 50 | |
| 51 void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { | |
| 52 // No-op. Return address is in lr register. | |
| 53 } | |
| 54 | |
| 55 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 47 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
| 56 MacroAssembler* masm, Label* miss_label, Register receiver, | 48 MacroAssembler* masm, Label* miss_label, Register receiver, |
| 57 Handle<Name> name, Register scratch0, Register scratch1) { | 49 Handle<Name> name, Register scratch0, Register scratch1) { |
| 58 DCHECK(!AreAliased(receiver, scratch0, scratch1)); | 50 DCHECK(!AreAliased(receiver, scratch0, scratch1)); |
| 59 DCHECK(name->IsUniqueName()); | 51 DCHECK(name->IsUniqueName()); |
| 60 Counters* counters = masm->isolate()->counters(); | 52 Counters* counters = masm->isolate()->counters(); |
| 61 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 53 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
| 62 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 54 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| 63 | 55 |
| 64 Label done; | 56 Label done; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 84 // Check that the properties array is a dictionary. | 76 // Check that the properties array is a dictionary. |
| 85 __ Ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); | 77 __ Ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
| 86 __ JumpIfNotRoot(map, Heap::kHashTableMapRootIndex, miss_label); | 78 __ JumpIfNotRoot(map, Heap::kHashTableMapRootIndex, miss_label); |
| 87 | 79 |
| 88 NameDictionaryLookupStub::GenerateNegativeLookup( | 80 NameDictionaryLookupStub::GenerateNegativeLookup( |
| 89 masm, miss_label, &done, receiver, properties, name, scratch1); | 81 masm, miss_label, &done, receiver, properties, name, scratch1); |
| 90 __ Bind(&done); | 82 __ Bind(&done); |
| 91 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 83 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| 92 } | 84 } |
| 93 | 85 |
| 94 | |
| 95 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( | |
| 96 MacroAssembler* masm, int index, Register result, Label* miss) { | |
| 97 __ LoadNativeContextSlot(index, result); | |
| 98 // Load its initial map. The global functions all have initial maps. | |
| 99 __ Ldr(result, | |
| 100 FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset)); | |
| 101 // Load the prototype from the initial map. | |
| 102 __ Ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); | |
| 103 } | |
| 104 | |
| 105 | |
| 106 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( | 86 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
| 107 MacroAssembler* masm, Register receiver, Register scratch1, | 87 MacroAssembler* masm, Register receiver, Register scratch1, |
| 108 Register scratch2, Label* miss_label) { | 88 Register scratch2, Label* miss_label) { |
| 109 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 89 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 110 // TryGetFunctionPrototype can't put the result directly in x0 because the | 90 // TryGetFunctionPrototype can't put the result directly in x0 because the |
| 111 // 3 inputs registers can't alias and we call this function from | 91 // 3 inputs registers can't alias and we call this function from |
| 112 // LoadIC::GenerateFunctionPrototype, where receiver is x0. So we explicitly | 92 // LoadIC::GenerateFunctionPrototype, where receiver is x0. So we explicitly |
| 113 // move the result in x0. | 93 // move the result in x0. |
| 114 __ Mov(x0, scratch1); | 94 __ Mov(x0, scratch1); |
| 115 __ Ret(); | 95 __ Ret(); |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 | 359 |
| 380 | 360 |
| 381 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, | 361 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, |
| 382 Handle<Name> name) { | 362 Handle<Name> name) { |
| 383 if (!label->is_unused()) { | 363 if (!label->is_unused()) { |
| 384 __ Bind(label); | 364 __ Bind(label); |
| 385 __ Mov(this->name(), Operand(name)); | 365 __ Mov(this->name(), Operand(name)); |
| 386 } | 366 } |
| 387 } | 367 } |
| 388 | 368 |
| 389 | |
| 390 void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { | |
| 391 __ Mov(this->name(), Operand(name)); | |
| 392 } | |
| 393 | |
| 394 | |
| 395 void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, | |
| 396 Register map_reg, | |
| 397 Register scratch, | |
| 398 Label* miss) { | |
| 399 Handle<WeakCell> cell = Map::WeakCellForMap(transition); | |
| 400 DCHECK(!map_reg.is(scratch)); | |
| 401 __ LoadWeakValue(map_reg, cell, miss); | |
| 402 if (transition->CanBeDeprecated()) { | |
| 403 __ Ldrsw(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset)); | |
| 404 __ TestAndBranchIfAnySet(scratch, Map::Deprecated::kMask, miss); | |
| 405 } | |
| 406 } | |
| 407 | |
| 408 | |
| 409 void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg, | |
| 410 int descriptor, | |
| 411 Register value_reg, | |
| 412 Register scratch, | |
| 413 Label* miss_label) { | |
| 414 DCHECK(!map_reg.is(scratch)); | |
| 415 DCHECK(!map_reg.is(value_reg)); | |
| 416 DCHECK(!value_reg.is(scratch)); | |
| 417 __ LoadInstanceDescriptors(map_reg, scratch); | |
| 418 __ Ldr(scratch, | |
| 419 FieldMemOperand(scratch, DescriptorArray::GetValueOffset(descriptor))); | |
| 420 __ Cmp(value_reg, scratch); | |
| 421 __ B(ne, miss_label); | |
| 422 } | |
| 423 | |
| 424 void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type, | |
| 425 Register value_reg, | |
| 426 Label* miss_label) { | |
| 427 Register map_reg = scratch1(); | |
| 428 Register scratch = scratch2(); | |
| 429 DCHECK(!value_reg.is(map_reg)); | |
| 430 DCHECK(!value_reg.is(scratch)); | |
| 431 __ JumpIfSmi(value_reg, miss_label); | |
| 432 if (field_type->IsClass()) { | |
| 433 __ Ldr(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | |
| 434 __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), | |
| 435 scratch); | |
| 436 __ B(ne, miss_label); | |
| 437 } | |
| 438 } | |
| 439 | |
| 440 void PropertyHandlerCompiler::GenerateAccessCheck( | 369 void PropertyHandlerCompiler::GenerateAccessCheck( |
| 441 Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2, | 370 Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2, |
| 442 Label* miss, bool compare_native_contexts_only) { | 371 Label* miss, bool compare_native_contexts_only) { |
| 443 Label done; | 372 Label done; |
| 444 // Load current native context. | 373 // Load current native context. |
| 445 __ Ldr(scratch1, NativeContextMemOperand()); | 374 __ Ldr(scratch1, NativeContextMemOperand()); |
| 446 // Load expected native context. | 375 // Load expected native context. |
| 447 __ LoadWeakValue(scratch2, native_context_cell, miss); | 376 __ LoadWeakValue(scratch2, native_context_cell, miss); |
| 448 __ Cmp(scratch1, scratch2); | 377 __ Cmp(scratch1, scratch2); |
| 449 | 378 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 __ B(&success); | 494 __ B(&success); |
| 566 | 495 |
| 567 GenerateRestoreName(miss, name); | 496 GenerateRestoreName(miss, name); |
| 568 if (IC::ICUseVector(kind())) PopVectorAndSlot(); | 497 if (IC::ICUseVector(kind())) PopVectorAndSlot(); |
| 569 TailCallBuiltin(masm(), MissBuiltin(kind())); | 498 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 570 | 499 |
| 571 __ Bind(&success); | 500 __ Bind(&success); |
| 572 } | 501 } |
| 573 } | 502 } |
| 574 | 503 |
| 575 | |
| 576 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | |
| 577 // Return the constant value. | |
| 578 __ LoadObject(x0, value); | |
| 579 __ Ret(); | |
| 580 } | |
| 581 | |
| 582 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( | 504 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( |
| 583 LookupIterator* it, Register holder_reg) { | 505 LookupIterator* it, Register holder_reg) { |
| 584 DCHECK(!AreAliased(receiver(), this->name(), scratch1(), scratch2(), | 506 DCHECK(!AreAliased(receiver(), this->name(), scratch1(), scratch2(), |
| 585 scratch3())); | 507 scratch3())); |
| 586 DCHECK(holder()->HasNamedInterceptor()); | 508 DCHECK(holder()->HasNamedInterceptor()); |
| 587 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); | 509 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); |
| 588 | 510 |
| 589 // Compile the interceptor call, followed by inline code to load the | 511 // Compile the interceptor call, followed by inline code to load the |
| 590 // property from further up the prototype chain if the call fails. | 512 // property from further up the prototype chain if the call fails. |
| 591 // Check that the maps haven't changed. | 513 // Check that the maps haven't changed. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 // Return the generated code. | 606 // Return the generated code. |
| 685 return GetCode(kind(), name); | 607 return GetCode(kind(), name); |
| 686 } | 608 } |
| 687 | 609 |
| 688 | 610 |
| 689 #undef __ | 611 #undef __ |
| 690 } // namespace internal | 612 } // namespace internal |
| 691 } // namespace v8 | 613 } // namespace v8 |
| 692 | 614 |
| 693 #endif // V8_TARGET_ARCH_IA32 | 615 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |