| 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 StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 20 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
| 21 Label* miss_label, | 21 MacroAssembler* masm, Label* miss_label, Register receiver, |
| 22 Register receiver, | 22 Handle<Name> name, Register scratch0, Register scratch1) { |
| 23 Handle<Name> name, | |
| 24 Register scratch0, | |
| 25 Register scratch1) { | |
| 26 ASSERT(!AreAliased(receiver, scratch0, scratch1)); | 23 ASSERT(!AreAliased(receiver, scratch0, scratch1)); |
| 27 ASSERT(name->IsUniqueName()); | 24 ASSERT(name->IsUniqueName()); |
| 28 Counters* counters = masm->isolate()->counters(); | 25 Counters* counters = masm->isolate()->counters(); |
| 29 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 26 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
| 30 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 27 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| 31 | 28 |
| 32 Label done; | 29 Label done; |
| 33 | 30 |
| 34 const int kInterceptorOrAccessCheckNeededMask = | 31 const int kInterceptorOrAccessCheckNeededMask = |
| 35 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 32 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 scratch, extra, extra2, extra3); | 191 scratch, extra, extra2, extra3); |
| 195 | 192 |
| 196 // Cache miss: Fall-through and let caller handle the miss by | 193 // Cache miss: Fall-through and let caller handle the miss by |
| 197 // entering the runtime system. | 194 // entering the runtime system. |
| 198 __ Bind(&miss); | 195 __ Bind(&miss); |
| 199 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, | 196 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, |
| 200 extra2, extra3); | 197 extra2, extra3); |
| 201 } | 198 } |
| 202 | 199 |
| 203 | 200 |
| 204 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 201 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
| 205 int index, | 202 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
| 206 Register prototype) { | |
| 207 // Load the global or builtins object from the current context. | |
| 208 __ Ldr(prototype, GlobalObjectMemOperand()); | |
| 209 // Load the native context from the global or builtins object. | |
| 210 __ Ldr(prototype, | |
| 211 FieldMemOperand(prototype, GlobalObject::kNativeContextOffset)); | |
| 212 // Load the function from the native context. | |
| 213 __ Ldr(prototype, ContextMemOperand(prototype, index)); | |
| 214 // Load the initial map. The global functions all have initial maps. | |
| 215 __ Ldr(prototype, | |
| 216 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); | |
| 217 // Load the prototype from the initial map. | |
| 218 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | |
| 219 } | |
| 220 | |
| 221 | |
| 222 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | |
| 223 MacroAssembler* masm, | |
| 224 int index, | |
| 225 Register prototype, | |
| 226 Label* miss) { | |
| 227 Isolate* isolate = masm->isolate(); | 203 Isolate* isolate = masm->isolate(); |
| 228 // Get the global function with the given index. | 204 // Get the global function with the given index. |
| 229 Handle<JSFunction> function( | 205 Handle<JSFunction> function( |
| 230 JSFunction::cast(isolate->native_context()->get(index))); | 206 JSFunction::cast(isolate->native_context()->get(index))); |
| 231 | 207 |
| 232 // Check we're still in the same context. | 208 // Check we're still in the same context. |
| 233 Register scratch = prototype; | 209 Register scratch = prototype; |
| 234 __ Ldr(scratch, GlobalObjectMemOperand()); | 210 __ Ldr(scratch, GlobalObjectMemOperand()); |
| 235 __ Ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); | 211 __ Ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
| 236 __ Ldr(scratch, ContextMemOperand(scratch, index)); | 212 __ Ldr(scratch, ContextMemOperand(scratch, index)); |
| 237 __ Cmp(scratch, Operand(function)); | 213 __ Cmp(scratch, Operand(function)); |
| 238 __ B(ne, miss); | 214 __ B(ne, miss); |
| 239 | 215 |
| 240 // Load its initial map. The global functions all have initial maps. | 216 // Load its initial map. The global functions all have initial maps. |
| 241 __ Mov(prototype, Operand(Handle<Map>(function->initial_map()))); | 217 __ Mov(prototype, Operand(Handle<Map>(function->initial_map()))); |
| 242 // Load the prototype from the initial map. | 218 // Load the prototype from the initial map. |
| 243 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 219 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
| 244 } | 220 } |
| 245 | 221 |
| 246 | 222 |
| 247 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 223 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
| 248 Register dst, | 224 MacroAssembler* masm, Register receiver, Register scratch1, |
| 249 Register src, | 225 Register scratch2, Label* miss_label) { |
| 250 bool inobject, | |
| 251 int index, | |
| 252 Representation representation) { | |
| 253 ASSERT(!representation.IsDouble()); | |
| 254 USE(representation); | |
| 255 if (inobject) { | |
| 256 int offset = index * kPointerSize; | |
| 257 __ Ldr(dst, FieldMemOperand(src, offset)); | |
| 258 } else { | |
| 259 // Calculate the offset into the properties array. | |
| 260 int offset = index * kPointerSize + FixedArray::kHeaderSize; | |
| 261 __ Ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); | |
| 262 __ Ldr(dst, FieldMemOperand(dst, offset)); | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 | |
| 267 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | |
| 268 Register receiver, | |
| 269 Register scratch, | |
| 270 Label* miss_label) { | |
| 271 ASSERT(!AreAliased(receiver, scratch)); | |
| 272 | |
| 273 // Check that the receiver isn't a smi. | |
| 274 __ JumpIfSmi(receiver, miss_label); | |
| 275 | |
| 276 // Check that the object is a JS array. | |
| 277 __ JumpIfNotObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE, | |
| 278 miss_label); | |
| 279 | |
| 280 // Load length directly from the JS array. | |
| 281 __ Ldr(x0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 282 __ Ret(); | |
| 283 } | |
| 284 | |
| 285 | |
| 286 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | |
| 287 Register receiver, | |
| 288 Register scratch1, | |
| 289 Register scratch2, | |
| 290 Label* miss_label) { | |
| 291 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 226 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 292 // TryGetFunctionPrototype can't put the result directly in x0 because the | 227 // TryGetFunctionPrototype can't put the result directly in x0 because the |
| 293 // 3 inputs registers can't alias and we call this function from | 228 // 3 inputs registers can't alias and we call this function from |
| 294 // LoadIC::GenerateFunctionPrototype, where receiver is x0. So we explicitly | 229 // LoadIC::GenerateFunctionPrototype, where receiver is x0. So we explicitly |
| 295 // move the result in x0. | 230 // move the result in x0. |
| 296 __ Mov(x0, scratch1); | 231 __ Mov(x0, scratch1); |
| 297 __ Ret(); | 232 __ Ret(); |
| 298 } | 233 } |
| 299 | 234 |
| 300 | 235 |
| 301 // 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 |
| 302 // 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 |
| 303 // property. | 238 // property. |
| 304 void StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm, | 239 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
| 305 Handle<JSGlobalObject> global, | 240 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
| 306 Handle<Name> name, | 241 Register scratch, Label* miss) { |
| 307 Register scratch, | |
| 308 Label* miss) { | |
| 309 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 242 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
| 310 ASSERT(cell->value()->IsTheHole()); | 243 ASSERT(cell->value()->IsTheHole()); |
| 311 __ Mov(scratch, Operand(cell)); | 244 __ Mov(scratch, Operand(cell)); |
| 312 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 245 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
| 313 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); | 246 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); |
| 314 } | 247 } |
| 315 | 248 |
| 316 | 249 |
| 317 void StoreStubCompiler::GenerateNegativeHolderLookup( | 250 void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( |
| 318 MacroAssembler* masm, | 251 MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg, |
| 319 Handle<JSObject> holder, | 252 Handle<Name> name, Label* miss) { |
| 320 Register holder_reg, | |
| 321 Handle<Name> name, | |
| 322 Label* miss) { | |
| 323 if (holder->IsJSGlobalObject()) { | 253 if (holder->IsJSGlobalObject()) { |
| 324 GenerateCheckPropertyCell( | 254 GenerateCheckPropertyCell( |
| 325 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); | 255 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); |
| 326 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 256 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 327 GenerateDictionaryNegativeLookup( | 257 GenerateDictionaryNegativeLookup( |
| 328 masm, miss, holder_reg, name, scratch1(), scratch2()); | 258 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 329 } | 259 } |
| 330 } | 260 } |
| 331 | 261 |
| 332 | 262 |
| 333 // Generate StoreTransition code, value is passed in x0 register. | 263 // Generate StoreTransition code, value is passed in x0 register. |
| 334 // When leaving generated code after success, the receiver_reg and storage_reg | 264 // When leaving generated code after success, the receiver_reg and storage_reg |
| 335 // may be clobbered. Upon branch to miss_label, the receiver and name registers | 265 // may be clobbered. Upon branch to miss_label, the receiver and name registers |
| 336 // have their original values. | 266 // have their original values. |
| 337 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 267 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
| 338 Handle<JSObject> object, | 268 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
| 339 LookupResult* lookup, | 269 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
| 340 Handle<Map> transition, | 270 Register storage_reg, Register value_reg, Register scratch1, |
| 341 Handle<Name> name, | 271 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { |
| 342 Register receiver_reg, | |
| 343 Register storage_reg, | |
| 344 Register value_reg, | |
| 345 Register scratch1, | |
| 346 Register scratch2, | |
| 347 Register scratch3, | |
| 348 Label* miss_label, | |
| 349 Label* slow) { | |
| 350 Label exit; | 272 Label exit; |
| 351 | 273 |
| 352 ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg, | 274 ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg, |
| 353 scratch1, scratch2, scratch3)); | 275 scratch1, scratch2, scratch3)); |
| 354 | 276 |
| 355 // We don't need scratch3. | 277 // We don't need scratch3. |
| 356 scratch3 = NoReg; | 278 scratch3 = NoReg; |
| 357 | 279 |
| 358 int descriptor = transition->LastAdded(); | 280 int descriptor = transition->LastAdded(); |
| 359 DescriptorArray* descriptors = transition->instance_descriptors(); | 281 DescriptorArray* descriptors = transition->instance_descriptors(); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 // Return the value (register x0). | 422 // Return the value (register x0). |
| 501 ASSERT(value_reg.is(x0)); | 423 ASSERT(value_reg.is(x0)); |
| 502 __ Ret(); | 424 __ Ret(); |
| 503 } | 425 } |
| 504 | 426 |
| 505 | 427 |
| 506 // Generate StoreField code, value is passed in x0 register. | 428 // Generate StoreField code, value is passed in x0 register. |
| 507 // When leaving generated code after success, the receiver_reg and name_reg may | 429 // When leaving generated code after success, the receiver_reg and name_reg may |
| 508 // be clobbered. Upon branch to miss_label, the receiver and name registers have | 430 // be clobbered. Upon branch to miss_label, the receiver and name registers have |
| 509 // their original values. | 431 // their original values. |
| 510 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 432 void NamedStoreHandlerCompiler::GenerateStoreField( |
| 511 Handle<JSObject> object, | 433 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
| 512 LookupResult* lookup, | 434 Register receiver_reg, Register name_reg, Register value_reg, |
| 513 Register receiver_reg, | 435 Register scratch1, Register scratch2, Label* miss_label) { |
| 514 Register name_reg, | |
| 515 Register value_reg, | |
| 516 Register scratch1, | |
| 517 Register scratch2, | |
| 518 Label* miss_label) { | |
| 519 // x0 : value | 436 // x0 : value |
| 520 Label exit; | 437 Label exit; |
| 521 | 438 |
| 522 // Stub never generated for non-global objects that require access | 439 // Stub never generated for non-global objects that require access |
| 523 // checks. | 440 // checks. |
| 524 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 441 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 525 | 442 |
| 526 FieldIndex index = lookup->GetFieldIndex(); | 443 FieldIndex index = lookup->GetFieldIndex(); |
| 527 | 444 |
| 528 Representation representation = lookup->representation(); | 445 Representation representation = lookup->representation(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 } | 545 } |
| 629 } | 546 } |
| 630 | 547 |
| 631 __ Bind(&exit); | 548 __ Bind(&exit); |
| 632 // Return the value (register x0). | 549 // Return the value (register x0). |
| 633 ASSERT(value_reg.is(x0)); | 550 ASSERT(value_reg.is(x0)); |
| 634 __ Ret(); | 551 __ Ret(); |
| 635 } | 552 } |
| 636 | 553 |
| 637 | 554 |
| 638 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 555 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 639 Label* label, | 556 Label* label, |
| 640 Handle<Name> name) { | 557 Handle<Name> name) { |
| 641 if (!label->is_unused()) { | 558 if (!label->is_unused()) { |
| 642 __ Bind(label); | 559 __ Bind(label); |
| 643 __ Mov(this->name(), Operand(name)); | 560 __ Mov(this->name(), Operand(name)); |
| 644 } | 561 } |
| 645 } | 562 } |
| 646 | 563 |
| 647 | 564 |
| 648 static void PushInterceptorArguments(MacroAssembler* masm, | 565 static void PushInterceptorArguments(MacroAssembler* masm, |
| 649 Register receiver, | 566 Register receiver, |
| 650 Register holder, | 567 Register holder, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 674 IC::UtilityId id) { | 591 IC::UtilityId id) { |
| 675 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 592 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 676 | 593 |
| 677 __ CallExternalReference( | 594 __ CallExternalReference( |
| 678 ExternalReference(IC_Utility(id), masm->isolate()), | 595 ExternalReference(IC_Utility(id), masm->isolate()), |
| 679 StubCache::kInterceptorArgsLength); | 596 StubCache::kInterceptorArgsLength); |
| 680 } | 597 } |
| 681 | 598 |
| 682 | 599 |
| 683 // Generate call to api function. | 600 // Generate call to api function. |
| 684 void StubCompiler::GenerateFastApiCall(MacroAssembler* masm, | 601 void PropertyHandlerCompiler::GenerateFastApiCall( |
| 685 const CallOptimization& optimization, | 602 MacroAssembler* masm, const CallOptimization& optimization, |
| 686 Handle<Map> receiver_map, | 603 Handle<Map> receiver_map, Register receiver, Register scratch, |
| 687 Register receiver, | 604 bool is_store, int argc, Register* values) { |
| 688 Register scratch, | |
| 689 bool is_store, | |
| 690 int argc, | |
| 691 Register* values) { | |
| 692 ASSERT(!AreAliased(receiver, scratch)); | 605 ASSERT(!AreAliased(receiver, scratch)); |
| 693 | 606 |
| 694 MacroAssembler::PushPopQueue queue(masm); | 607 MacroAssembler::PushPopQueue queue(masm); |
| 695 queue.Queue(receiver); | 608 queue.Queue(receiver); |
| 696 // Write the arguments to the stack frame. | 609 // Write the arguments to the stack frame. |
| 697 for (int i = 0; i < argc; i++) { | 610 for (int i = 0; i < argc; i++) { |
| 698 Register arg = values[argc-1-i]; | 611 Register arg = values[argc-1-i]; |
| 699 ASSERT(!AreAliased(receiver, scratch, arg)); | 612 ASSERT(!AreAliased(receiver, scratch, arg)); |
| 700 queue.Queue(arg); | 613 queue.Queue(arg); |
| 701 } | 614 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 ExternalReference::DIRECT_API_CALL, | 665 ExternalReference::DIRECT_API_CALL, |
| 753 masm->isolate()); | 666 masm->isolate()); |
| 754 __ Mov(api_function_address, ref); | 667 __ Mov(api_function_address, ref); |
| 755 | 668 |
| 756 // Jump to stub. | 669 // Jump to stub. |
| 757 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 670 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
| 758 __ TailCallStub(&stub); | 671 __ TailCallStub(&stub); |
| 759 } | 672 } |
| 760 | 673 |
| 761 | 674 |
| 762 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 675 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
| 676 Handle<Code> code) { |
| 763 __ Jump(code, RelocInfo::CODE_TARGET); | 677 __ Jump(code, RelocInfo::CODE_TARGET); |
| 764 } | 678 } |
| 765 | 679 |
| 766 | 680 |
| 767 #undef __ | 681 #undef __ |
| 768 #define __ ACCESS_MASM(masm()) | 682 #define __ ACCESS_MASM(masm()) |
| 769 | 683 |
| 770 | 684 |
| 771 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 685 Register PropertyHandlerCompiler::CheckPrototypes( |
| 772 Register object_reg, | 686 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, |
| 773 Handle<JSObject> holder, | 687 Register holder_reg, Register scratch1, Register scratch2, |
| 774 Register holder_reg, | 688 Handle<Name> name, Label* miss, PrototypeCheckType check) { |
| 775 Register scratch1, | |
| 776 Register scratch2, | |
| 777 Handle<Name> name, | |
| 778 Label* miss, | |
| 779 PrototypeCheckType check) { | |
| 780 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 689 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 781 | 690 |
| 782 // object_reg and holder_reg registers can alias. | 691 // object_reg and holder_reg registers can alias. |
| 783 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); | 692 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); |
| 784 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); | 693 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); |
| 785 | 694 |
| 786 // Keep track of the current object in register reg. | 695 // Keep track of the current object in register reg. |
| 787 Register reg = object_reg; | 696 Register reg = object_reg; |
| 788 int depth = 0; | 697 int depth = 0; |
| 789 | 698 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 !current_map->is_access_check_needed()); | 785 !current_map->is_access_check_needed()); |
| 877 if (current_map->IsJSGlobalProxyMap()) { | 786 if (current_map->IsJSGlobalProxyMap()) { |
| 878 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 787 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
| 879 } | 788 } |
| 880 | 789 |
| 881 // Return the register containing the holder. | 790 // Return the register containing the holder. |
| 882 return reg; | 791 return reg; |
| 883 } | 792 } |
| 884 | 793 |
| 885 | 794 |
| 886 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 795 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
| 887 if (!miss->is_unused()) { | 796 if (!miss->is_unused()) { |
| 888 Label success; | 797 Label success; |
| 889 __ B(&success); | 798 __ B(&success); |
| 890 | 799 |
| 891 __ Bind(miss); | 800 __ Bind(miss); |
| 892 TailCallBuiltin(masm(), MissBuiltin(kind())); | 801 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 893 | 802 |
| 894 __ Bind(&success); | 803 __ Bind(&success); |
| 895 } | 804 } |
| 896 } | 805 } |
| 897 | 806 |
| 898 | 807 |
| 899 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 808 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
| 900 if (!miss->is_unused()) { | 809 if (!miss->is_unused()) { |
| 901 Label success; | 810 Label success; |
| 902 __ B(&success); | 811 __ B(&success); |
| 903 | 812 |
| 904 GenerateRestoreName(masm(), miss, name); | 813 GenerateRestoreName(masm(), miss, name); |
| 905 TailCallBuiltin(masm(), MissBuiltin(kind())); | 814 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 906 | 815 |
| 907 __ Bind(&success); | 816 __ Bind(&success); |
| 908 } | 817 } |
| 909 } | 818 } |
| 910 | 819 |
| 911 | 820 |
| 912 Register LoadStubCompiler::CallbackHandlerFrontend(Handle<HeapType> type, | 821 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
| 913 Register object_reg, | 822 Register object_reg, |
| 914 Handle<JSObject> holder, | 823 Handle<JSObject> holder, |
| 915 Handle<Name> name, | 824 Handle<Name> name, |
| 916 Handle<Object> callback) { | 825 Handle<Object> callback) { |
| 917 Label miss; | 826 Label miss; |
| 918 | 827 |
| 919 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 828 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); |
| 920 // HandlerFrontendHeader can return its result into scratch1() so do not | 829 // FrontendHeader can return its result into scratch1() so do not |
| 921 // use it. | 830 // use it. |
| 922 Register scratch2 = this->scratch2(); | 831 Register scratch2 = this->scratch2(); |
| 923 Register scratch3 = this->scratch3(); | 832 Register scratch3 = this->scratch3(); |
| 924 Register dictionary = this->scratch4(); | 833 Register dictionary = this->scratch4(); |
| 925 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); | 834 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); |
| 926 | 835 |
| 927 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 836 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 928 // Load the properties dictionary. | 837 // Load the properties dictionary. |
| 929 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 838 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
| 930 | 839 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 943 // pointer into the dictionary. Check that the value is the callback. | 852 // pointer into the dictionary. Check that the value is the callback. |
| 944 Register pointer = scratch3; | 853 Register pointer = scratch3; |
| 945 const int kElementsStartOffset = NameDictionary::kHeaderSize + | 854 const int kElementsStartOffset = NameDictionary::kHeaderSize + |
| 946 NameDictionary::kElementsStartIndex * kPointerSize; | 855 NameDictionary::kElementsStartIndex * kPointerSize; |
| 947 const int kValueOffset = kElementsStartOffset + kPointerSize; | 856 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 948 __ Ldr(scratch2, FieldMemOperand(pointer, kValueOffset)); | 857 __ Ldr(scratch2, FieldMemOperand(pointer, kValueOffset)); |
| 949 __ Cmp(scratch2, Operand(callback)); | 858 __ Cmp(scratch2, Operand(callback)); |
| 950 __ B(ne, &miss); | 859 __ B(ne, &miss); |
| 951 } | 860 } |
| 952 | 861 |
| 953 HandlerFrontendFooter(name, &miss); | 862 FrontendFooter(name, &miss); |
| 954 return reg; | 863 return reg; |
| 955 } | 864 } |
| 956 | 865 |
| 957 | 866 |
| 958 void LoadStubCompiler::GenerateLoadField(Register reg, | 867 void NamedLoadHandlerCompiler::GenerateLoadField( |
| 959 Handle<JSObject> holder, | 868 Register reg, Handle<JSObject> holder, FieldIndex field, |
| 960 FieldIndex field, | 869 Representation representation) { |
| 961 Representation representation) { | |
| 962 __ Mov(receiver(), reg); | 870 __ Mov(receiver(), reg); |
| 963 LoadFieldStub stub(isolate(), field); | 871 LoadFieldStub stub(isolate(), field); |
| 964 GenerateTailCall(masm(), stub.GetCode()); | 872 GenerateTailCall(masm(), stub.GetCode()); |
| 965 } | 873 } |
| 966 | 874 |
| 967 | 875 |
| 968 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 876 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 969 // Return the constant value. | 877 // Return the constant value. |
| 970 __ LoadObject(x0, value); | 878 __ LoadObject(x0, value); |
| 971 __ Ret(); | 879 __ Ret(); |
| 972 } | 880 } |
| 973 | 881 |
| 974 | 882 |
| 975 void LoadStubCompiler::GenerateLoadCallback( | 883 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
| 976 Register reg, | 884 Register reg, Handle<ExecutableAccessorInfo> callback) { |
| 977 Handle<ExecutableAccessorInfo> callback) { | |
| 978 ASSERT(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); | 885 ASSERT(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); |
| 979 | 886 |
| 980 // Build ExecutableAccessorInfo::args_ list on the stack and push property | 887 // Build ExecutableAccessorInfo::args_ list on the stack and push property |
| 981 // name below the exit frame to make GC aware of them and store pointers to | 888 // name below the exit frame to make GC aware of them and store pointers to |
| 982 // them. | 889 // them. |
| 983 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 890 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
| 984 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 891 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
| 985 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 892 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
| 986 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 893 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
| 987 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 894 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 ApiFunction fun(getter_address); | 927 ApiFunction fun(getter_address); |
| 1021 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 928 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
| 1022 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 929 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
| 1023 __ Mov(getter_address_reg, ref); | 930 __ Mov(getter_address_reg, ref); |
| 1024 | 931 |
| 1025 CallApiGetterStub stub(isolate()); | 932 CallApiGetterStub stub(isolate()); |
| 1026 __ TailCallStub(&stub); | 933 __ TailCallStub(&stub); |
| 1027 } | 934 } |
| 1028 | 935 |
| 1029 | 936 |
| 1030 void LoadStubCompiler::GenerateLoadInterceptor( | 937 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
| 1031 Register holder_reg, | 938 Register holder_reg, Handle<Object> object, |
| 1032 Handle<Object> object, | 939 Handle<JSObject> interceptor_holder, LookupResult* lookup, |
| 1033 Handle<JSObject> interceptor_holder, | |
| 1034 LookupResult* lookup, | |
| 1035 Handle<Name> name) { | 940 Handle<Name> name) { |
| 1036 ASSERT(!AreAliased(receiver(), this->name(), | 941 ASSERT(!AreAliased(receiver(), this->name(), |
| 1037 scratch1(), scratch2(), scratch3())); | 942 scratch1(), scratch2(), scratch3())); |
| 1038 ASSERT(interceptor_holder->HasNamedInterceptor()); | 943 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1039 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 944 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1040 | 945 |
| 1041 // So far the most popular follow ups for interceptor loads are FIELD | 946 // So far the most popular follow ups for interceptor loads are FIELD |
| 1042 // and CALLBACKS, so inline only them, other cases may be added later. | 947 // and CALLBACKS, so inline only them, other cases may be added later. |
| 1043 bool compile_followup_inline = false; | 948 bool compile_followup_inline = false; |
| 1044 if (lookup->IsFound() && lookup->IsCacheable()) { | 949 if (lookup->IsFound() && lookup->IsCacheable()) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 masm(), receiver(), holder_reg, this->name(), interceptor_holder); | 1013 masm(), receiver(), holder_reg, this->name(), interceptor_holder); |
| 1109 | 1014 |
| 1110 ExternalReference ref = | 1015 ExternalReference ref = |
| 1111 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), | 1016 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), |
| 1112 isolate()); | 1017 isolate()); |
| 1113 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); | 1018 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
| 1114 } | 1019 } |
| 1115 } | 1020 } |
| 1116 | 1021 |
| 1117 | 1022 |
| 1118 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1023 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 1119 Handle<JSObject> object, | 1024 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
| 1120 Handle<JSObject> holder, | |
| 1121 Handle<Name> name, | |
| 1122 Handle<ExecutableAccessorInfo> callback) { | 1025 Handle<ExecutableAccessorInfo> callback) { |
| 1123 ASM_LOCATION("StoreStubCompiler::CompileStoreCallback"); | 1026 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); |
| 1124 Register holder_reg = HandlerFrontend( | 1027 Register holder_reg = |
| 1125 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | 1028 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
| 1126 | 1029 |
| 1127 // Stub never generated for non-global objects that require access checks. | 1030 // Stub never generated for non-global objects that require access checks. |
| 1128 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1031 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1129 | 1032 |
| 1130 // receiver() and holder_reg can alias. | 1033 // receiver() and holder_reg can alias. |
| 1131 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); | 1034 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); |
| 1132 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); | 1035 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); |
| 1133 __ Mov(scratch1(), Operand(callback)); | 1036 __ Mov(scratch1(), Operand(callback)); |
| 1134 __ Mov(scratch2(), Operand(name)); | 1037 __ Mov(scratch2(), Operand(name)); |
| 1135 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); | 1038 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); |
| 1136 | 1039 |
| 1137 // Do tail-call to the runtime system. | 1040 // Do tail-call to the runtime system. |
| 1138 ExternalReference store_callback_property = | 1041 ExternalReference store_callback_property = |
| 1139 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1042 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 1140 __ TailCallExternalReference(store_callback_property, 5, 1); | 1043 __ TailCallExternalReference(store_callback_property, 5, 1); |
| 1141 | 1044 |
| 1142 // Return the generated code. | 1045 // Return the generated code. |
| 1143 return GetCode(kind(), Code::FAST, name); | 1046 return GetCode(kind(), Code::FAST, name); |
| 1144 } | 1047 } |
| 1145 | 1048 |
| 1146 | 1049 |
| 1147 #undef __ | 1050 #undef __ |
| 1148 #define __ ACCESS_MASM(masm) | 1051 #define __ ACCESS_MASM(masm) |
| 1149 | 1052 |
| 1150 | 1053 |
| 1151 void StoreStubCompiler::GenerateStoreViaSetter( | 1054 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
| 1152 MacroAssembler* masm, | 1055 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 1153 Handle<HeapType> type, | |
| 1154 Register receiver, | |
| 1155 Handle<JSFunction> setter) { | 1056 Handle<JSFunction> setter) { |
| 1156 // ----------- S t a t e ------------- | 1057 // ----------- S t a t e ------------- |
| 1157 // -- lr : return address | 1058 // -- lr : return address |
| 1158 // ----------------------------------- | 1059 // ----------------------------------- |
| 1159 Label miss; | 1060 Label miss; |
| 1160 | 1061 |
| 1161 { | 1062 { |
| 1162 FrameScope scope(masm, StackFrame::INTERNAL); | 1063 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1163 | 1064 |
| 1164 // Save value register, so we can restore it later. | 1065 // Save value register, so we can restore it later. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1189 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1090 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1190 } | 1091 } |
| 1191 __ Ret(); | 1092 __ Ret(); |
| 1192 } | 1093 } |
| 1193 | 1094 |
| 1194 | 1095 |
| 1195 #undef __ | 1096 #undef __ |
| 1196 #define __ ACCESS_MASM(masm()) | 1097 #define __ ACCESS_MASM(masm()) |
| 1197 | 1098 |
| 1198 | 1099 |
| 1199 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 1100 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
| 1200 Handle<JSObject> object, | 1101 Handle<JSObject> object, Handle<Name> name) { |
| 1201 Handle<Name> name) { | |
| 1202 Label miss; | 1102 Label miss; |
| 1203 | 1103 |
| 1204 ASM_LOCATION("StoreStubCompiler::CompileStoreInterceptor"); | 1104 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor"); |
| 1205 | 1105 |
| 1206 __ Push(receiver(), this->name(), value()); | 1106 __ Push(receiver(), this->name(), value()); |
| 1207 | 1107 |
| 1208 // Do tail-call to the runtime system. | 1108 // Do tail-call to the runtime system. |
| 1209 ExternalReference store_ic_property = | 1109 ExternalReference store_ic_property = |
| 1210 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 1110 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 1211 __ TailCallExternalReference(store_ic_property, 3, 1); | 1111 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 1212 | 1112 |
| 1213 // Return the generated code. | 1113 // Return the generated code. |
| 1214 return GetCode(kind(), Code::FAST, name); | 1114 return GetCode(kind(), Code::FAST, name); |
| 1215 } | 1115 } |
| 1216 | 1116 |
| 1217 | 1117 |
| 1218 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, | 1118 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
| 1219 Handle<JSObject> last, | 1119 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { |
| 1220 Handle<Name> name) { | 1120 NonexistentFrontend(type, last, name); |
| 1221 NonexistentHandlerFrontend(type, last, name); | |
| 1222 | 1121 |
| 1223 // Return undefined if maps of the full prototype chain are still the | 1122 // Return undefined if maps of the full prototype chain are still the |
| 1224 // same and no global property with this name contains a value. | 1123 // same and no global property with this name contains a value. |
| 1225 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1124 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
| 1226 __ Ret(); | 1125 __ Ret(); |
| 1227 | 1126 |
| 1228 // Return the generated code. | 1127 // Return the generated code. |
| 1229 return GetCode(kind(), Code::FAST, name); | 1128 return GetCode(kind(), Code::FAST, name); |
| 1230 } | 1129 } |
| 1231 | 1130 |
| 1232 | 1131 |
| 1233 // TODO(all): The so-called scratch registers are significant in some cases. For | 1132 // TODO(all): The so-called scratch registers are significant in some cases. For |
| 1234 // example, KeyedStoreStubCompiler::registers()[3] (x3) is actually used for | 1133 // example, PropertyAccessCompiler::keyed_store_calling_convention()[3] (x3) is |
| 1235 // KeyedStoreCompiler::transition_map(). We should verify which registers are | 1134 // actually |
| 1236 // actually scratch registers, and which are important. For now, we use the same | 1135 // used for KeyedStoreCompiler::transition_map(). We should verify which |
| 1237 // assignments as ARM to remain on the safe side. | 1136 // registers are actually scratch registers, and which are important. For now, |
| 1137 // we use the same assignments as ARM to remain on the safe side. |
| 1238 | 1138 |
| 1239 Register* LoadStubCompiler::registers() { | 1139 Register* PropertyAccessCompiler::load_calling_convention() { |
| 1240 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1140 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
| 1241 Register receiver = LoadIC::ReceiverRegister(); | 1141 Register receiver = LoadIC::ReceiverRegister(); |
| 1242 Register name = LoadIC::NameRegister(); | 1142 Register name = LoadIC::NameRegister(); |
| 1243 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; | 1143 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; |
| 1244 return registers; | 1144 return registers; |
| 1245 } | 1145 } |
| 1246 | 1146 |
| 1247 | 1147 |
| 1248 Register* KeyedLoadStubCompiler::registers() { | 1148 Register* PropertyAccessCompiler::store_calling_convention() { |
| 1249 // receiver, name, scratch1, scratch2, scratch3, scratch4. | |
| 1250 Register receiver = LoadIC::ReceiverRegister(); | |
| 1251 Register name = LoadIC::NameRegister(); | |
| 1252 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; | |
| 1253 return registers; | |
| 1254 } | |
| 1255 | |
| 1256 | |
| 1257 Register StoreStubCompiler::value() { | |
| 1258 return StoreIC::ValueRegister(); | |
| 1259 } | |
| 1260 | |
| 1261 | |
| 1262 Register* StoreStubCompiler::registers() { | |
| 1263 // receiver, value, scratch1, scratch2, scratch3. | 1149 // receiver, value, scratch1, scratch2, scratch3. |
| 1264 Register receiver = StoreIC::ReceiverRegister(); | 1150 Register receiver = StoreIC::ReceiverRegister(); |
| 1265 Register name = StoreIC::NameRegister(); | 1151 Register name = StoreIC::NameRegister(); |
| 1266 static Register registers[] = { receiver, name, x3, x4, x5 }; | 1152 static Register registers[] = { receiver, name, x3, x4, x5 }; |
| 1267 return registers; | 1153 return registers; |
| 1268 } | 1154 } |
| 1269 | 1155 |
| 1270 | 1156 |
| 1271 Register* KeyedStoreStubCompiler::registers() { | 1157 Register* PropertyAccessCompiler::keyed_store_calling_convention() { |
| 1272 // receiver, name, scratch1/map, scratch2, scratch3. | 1158 // receiver, name, scratch1/map, scratch2, scratch3. |
| 1273 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1159 Register receiver = KeyedStoreIC::ReceiverRegister(); |
| 1274 Register name = KeyedStoreIC::NameRegister(); | 1160 Register name = KeyedStoreIC::NameRegister(); |
| 1275 Register map = KeyedStoreIC::MapRegister(); | 1161 Register map = KeyedStoreIC::MapRegister(); |
| 1276 static Register registers[] = { receiver, name, map, x4, x5 }; | 1162 static Register registers[] = { receiver, name, map, x4, x5 }; |
| 1277 return registers; | 1163 return registers; |
| 1278 } | 1164 } |
| 1279 | 1165 |
| 1280 | 1166 |
| 1167 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1168 |
| 1169 |
| 1281 #undef __ | 1170 #undef __ |
| 1282 #define __ ACCESS_MASM(masm) | 1171 #define __ ACCESS_MASM(masm) |
| 1283 | 1172 |
| 1284 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1173 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
| 1285 Handle<HeapType> type, | 1174 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 1286 Register receiver, | 1175 Handle<JSFunction> getter) { |
| 1287 Handle<JSFunction> getter) { | |
| 1288 { | 1176 { |
| 1289 FrameScope scope(masm, StackFrame::INTERNAL); | 1177 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1290 | 1178 |
| 1291 if (!getter.is_null()) { | 1179 if (!getter.is_null()) { |
| 1292 // Call the JavaScript getter with the receiver on the stack. | 1180 // Call the JavaScript getter with the receiver on the stack. |
| 1293 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 1181 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 1294 // Swap in the global receiver. | 1182 // Swap in the global receiver. |
| 1295 __ Ldr(receiver, | 1183 __ Ldr(receiver, |
| 1296 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 1184 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
| 1297 } | 1185 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1310 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1198 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1311 } | 1199 } |
| 1312 __ Ret(); | 1200 __ Ret(); |
| 1313 } | 1201 } |
| 1314 | 1202 |
| 1315 | 1203 |
| 1316 #undef __ | 1204 #undef __ |
| 1317 #define __ ACCESS_MASM(masm()) | 1205 #define __ ACCESS_MASM(masm()) |
| 1318 | 1206 |
| 1319 | 1207 |
| 1320 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 1208 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| 1321 Handle<HeapType> type, | 1209 Handle<HeapType> type, Handle<GlobalObject> global, |
| 1322 Handle<GlobalObject> global, | 1210 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
| 1323 Handle<PropertyCell> cell, | |
| 1324 Handle<Name> name, | |
| 1325 bool is_dont_delete) { | |
| 1326 Label miss; | 1211 Label miss; |
| 1327 HandlerFrontendHeader(type, receiver(), global, name, &miss); | 1212 FrontendHeader(type, receiver(), global, name, &miss); |
| 1328 | 1213 |
| 1329 // Get the value from the cell. | 1214 // Get the value from the cell. |
| 1330 __ Mov(x3, Operand(cell)); | 1215 __ Mov(x3, Operand(cell)); |
| 1331 __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset)); | 1216 __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset)); |
| 1332 | 1217 |
| 1333 // Check for deleted property if property can actually be deleted. | 1218 // Check for deleted property if property can actually be deleted. |
| 1334 if (!is_dont_delete) { | 1219 if (!is_dont_delete) { |
| 1335 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss); | 1220 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss); |
| 1336 } | 1221 } |
| 1337 | 1222 |
| 1338 Counters* counters = isolate()->counters(); | 1223 Counters* counters = isolate()->counters(); |
| 1339 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); | 1224 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); |
| 1340 __ Mov(x0, x4); | 1225 __ Mov(x0, x4); |
| 1341 __ Ret(); | 1226 __ Ret(); |
| 1342 | 1227 |
| 1343 HandlerFrontendFooter(name, &miss); | 1228 FrontendFooter(name, &miss); |
| 1344 | 1229 |
| 1345 // Return the generated code. | 1230 // Return the generated code. |
| 1346 return GetCode(kind(), Code::NORMAL, name); | 1231 return GetCode(kind(), Code::NORMAL, name); |
| 1347 } | 1232 } |
| 1348 | 1233 |
| 1349 | 1234 |
| 1350 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 1235 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
| 1351 TypeHandleList* types, | 1236 CodeHandleList* handlers, |
| 1352 CodeHandleList* handlers, | 1237 Handle<Name> name, |
| 1353 Handle<Name> name, | 1238 Code::StubType type, |
| 1354 Code::StubType type, | 1239 IcCheckType check) { |
| 1355 IcCheckType check) { | |
| 1356 Label miss; | 1240 Label miss; |
| 1357 | 1241 |
| 1358 if (check == PROPERTY && | 1242 if (check == PROPERTY && |
| 1359 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | 1243 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { |
| 1360 __ CompareAndBranch(this->name(), Operand(name), ne, &miss); | 1244 __ CompareAndBranch(this->name(), Operand(name), ne, &miss); |
| 1361 } | 1245 } |
| 1362 | 1246 |
| 1363 Label number_case; | 1247 Label number_case; |
| 1364 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1248 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
| 1365 __ JumpIfSmi(receiver(), smi_target); | 1249 __ JumpIfSmi(receiver(), smi_target); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1388 } | 1272 } |
| 1389 } | 1273 } |
| 1390 ASSERT(number_of_handled_maps != 0); | 1274 ASSERT(number_of_handled_maps != 0); |
| 1391 | 1275 |
| 1392 __ Bind(&miss); | 1276 __ Bind(&miss); |
| 1393 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1277 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1394 | 1278 |
| 1395 // Return the generated code. | 1279 // Return the generated code. |
| 1396 InlineCacheState state = | 1280 InlineCacheState state = |
| 1397 (number_of_handled_maps > 1) ? POLYMORPHIC : MONOMORPHIC; | 1281 (number_of_handled_maps > 1) ? POLYMORPHIC : MONOMORPHIC; |
| 1398 return GetICCode(kind(), type, name, state); | 1282 return GetCode(kind(), type, name, state); |
| 1399 } | 1283 } |
| 1400 | 1284 |
| 1401 | 1285 |
| 1402 void StoreStubCompiler::GenerateStoreArrayLength() { | 1286 void NamedStoreHandlerCompiler::GenerateStoreArrayLength() { |
| 1403 // Prepare tail call to StoreIC_ArrayLength. | 1287 // Prepare tail call to StoreIC_ArrayLength. |
| 1404 __ Push(receiver(), value()); | 1288 __ Push(receiver(), value()); |
| 1405 | 1289 |
| 1406 ExternalReference ref = | 1290 ExternalReference ref = |
| 1407 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), | 1291 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), |
| 1408 masm()->isolate()); | 1292 masm()->isolate()); |
| 1409 __ TailCallExternalReference(ref, 2, 1); | 1293 __ TailCallExternalReference(ref, 2, 1); |
| 1410 } | 1294 } |
| 1411 | 1295 |
| 1412 | 1296 |
| 1413 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 1297 Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( |
| 1414 MapHandleList* receiver_maps, | 1298 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
| 1415 CodeHandleList* handler_stubs, | |
| 1416 MapHandleList* transitioned_maps) { | 1299 MapHandleList* transitioned_maps) { |
| 1417 Label miss; | 1300 Label miss; |
| 1418 | 1301 |
| 1419 ASM_LOCATION("KeyedStoreStubCompiler::CompileStorePolymorphic"); | 1302 ASM_LOCATION("PropertyICCompiler::CompileStorePolymorphic"); |
| 1420 | 1303 |
| 1421 __ JumpIfSmi(receiver(), &miss); | 1304 __ JumpIfSmi(receiver(), &miss); |
| 1422 | 1305 |
| 1423 int receiver_count = receiver_maps->length(); | 1306 int receiver_count = receiver_maps->length(); |
| 1424 __ Ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 1307 __ Ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
| 1425 for (int i = 0; i < receiver_count; i++) { | 1308 for (int i = 0; i < receiver_count; i++) { |
| 1426 __ Cmp(scratch1(), Operand(receiver_maps->at(i))); | 1309 __ Cmp(scratch1(), Operand(receiver_maps->at(i))); |
| 1427 | 1310 |
| 1428 Label skip; | 1311 Label skip; |
| 1429 __ B(&skip, ne); | 1312 __ B(&skip, ne); |
| 1430 if (!transitioned_maps->at(i).is_null()) { | 1313 if (!transitioned_maps->at(i).is_null()) { |
| 1431 // This argument is used by the handler stub. For example, see | 1314 // This argument is used by the handler stub. For example, see |
| 1432 // ElementsTransitionGenerator::GenerateMapChangeElementsTransition. | 1315 // ElementsTransitionGenerator::GenerateMapChangeElementsTransition. |
| 1433 __ Mov(transition_map(), Operand(transitioned_maps->at(i))); | 1316 __ Mov(transition_map(), Operand(transitioned_maps->at(i))); |
| 1434 } | 1317 } |
| 1435 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 1318 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
| 1436 __ Bind(&skip); | 1319 __ Bind(&skip); |
| 1437 } | 1320 } |
| 1438 | 1321 |
| 1439 __ Bind(&miss); | 1322 __ Bind(&miss); |
| 1440 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1323 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1441 | 1324 |
| 1442 return GetICCode( | 1325 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 1443 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
| 1444 } | 1326 } |
| 1445 | 1327 |
| 1446 | 1328 |
| 1447 #undef __ | 1329 #undef __ |
| 1448 #define __ ACCESS_MASM(masm) | 1330 #define __ ACCESS_MASM(masm) |
| 1449 | 1331 |
| 1450 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( | 1332 void IndexedHandlerCompiler::GenerateLoadDictionaryElement( |
| 1451 MacroAssembler* masm) { | 1333 MacroAssembler* masm) { |
| 1452 // The return address is in lr. | 1334 // The return address is in lr. |
| 1453 Label slow, miss; | 1335 Label slow, miss; |
| 1454 | 1336 |
| 1455 Register result = x0; | 1337 Register result = x0; |
| 1456 Register key = LoadIC::NameRegister(); | 1338 Register key = LoadIC::NameRegister(); |
| 1457 Register receiver = LoadIC::ReceiverRegister(); | 1339 Register receiver = LoadIC::ReceiverRegister(); |
| 1458 ASSERT(receiver.is(x1)); | 1340 ASSERT(receiver.is(x1)); |
| 1459 ASSERT(key.is(x2)); | 1341 ASSERT(key.is(x2)); |
| 1460 | 1342 |
| 1461 __ JumpIfNotSmi(key, &miss); | 1343 __ JumpIfNotSmi(key, &miss); |
| 1462 __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 1344 __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 1463 __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6); | 1345 __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6); |
| 1464 __ Ret(); | 1346 __ Ret(); |
| 1465 | 1347 |
| 1466 __ Bind(&slow); | 1348 __ Bind(&slow); |
| 1467 __ IncrementCounter( | 1349 __ IncrementCounter( |
| 1468 masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3); | 1350 masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3); |
| 1469 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); | 1351 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
| 1470 | 1352 |
| 1471 // Miss case, call the runtime. | 1353 // Miss case, call the runtime. |
| 1472 __ Bind(&miss); | 1354 __ Bind(&miss); |
| 1473 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1355 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1474 } | 1356 } |
| 1475 | 1357 |
| 1476 | 1358 |
| 1477 } } // namespace v8::internal | 1359 } } // namespace v8::internal |
| 1478 | 1360 |
| 1479 #endif // V8_TARGET_ARCH_ARM64 | 1361 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |