| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 107 __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 108 __ jmp(offset); | 108 __ jmp(offset); |
| 109 | 109 |
| 110 // Pop at miss. | 110 // Pop at miss. |
| 111 __ bind(&miss); | 111 __ bind(&miss); |
| 112 __ pop(offset); | 112 __ pop(offset); |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 | 115 |
| 116 | 116 |
| 117 void StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 117 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
| 118 Label* miss_label, | 118 MacroAssembler* masm, Label* miss_label, Register receiver, |
| 119 Register receiver, | 119 Handle<Name> name, Register scratch0, Register scratch1) { |
| 120 Handle<Name> name, | |
| 121 Register scratch0, | |
| 122 Register scratch1) { | |
| 123 ASSERT(name->IsUniqueName()); | 120 ASSERT(name->IsUniqueName()); |
| 124 ASSERT(!receiver.is(scratch0)); | 121 ASSERT(!receiver.is(scratch0)); |
| 125 Counters* counters = masm->isolate()->counters(); | 122 Counters* counters = masm->isolate()->counters(); |
| 126 __ IncrementCounter(counters->negative_lookups(), 1); | 123 __ IncrementCounter(counters->negative_lookups(), 1); |
| 127 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 124 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 128 | 125 |
| 129 __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); | 126 __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 130 | 127 |
| 131 const int kInterceptorOrAccessCheckNeededMask = | 128 const int kInterceptorOrAccessCheckNeededMask = |
| 132 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 129 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 ProbeTable( | 223 ProbeTable( |
| 227 isolate(), masm, flags, kSecondary, name, receiver, offset, extra); | 224 isolate(), masm, flags, kSecondary, name, receiver, offset, extra); |
| 228 | 225 |
| 229 // Cache miss: Fall-through and let caller handle the miss by | 226 // Cache miss: Fall-through and let caller handle the miss by |
| 230 // entering the runtime system. | 227 // entering the runtime system. |
| 231 __ bind(&miss); | 228 __ bind(&miss); |
| 232 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 229 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
| 233 } | 230 } |
| 234 | 231 |
| 235 | 232 |
| 236 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 233 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
| 237 int index, | 234 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
| 238 Register prototype) { | |
| 239 __ LoadGlobalFunction(index, prototype); | |
| 240 __ LoadGlobalFunctionInitialMap(prototype, prototype); | |
| 241 // Load the prototype from the initial map. | |
| 242 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | |
| 243 } | |
| 244 | |
| 245 | |
| 246 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | |
| 247 MacroAssembler* masm, | |
| 248 int index, | |
| 249 Register prototype, | |
| 250 Label* miss) { | |
| 251 // Get the global function with the given index. | 235 // Get the global function with the given index. |
| 252 Handle<JSFunction> function( | 236 Handle<JSFunction> function( |
| 253 JSFunction::cast(masm->isolate()->native_context()->get(index))); | 237 JSFunction::cast(masm->isolate()->native_context()->get(index))); |
| 254 // Check we're still in the same context. | 238 // Check we're still in the same context. |
| 255 Register scratch = prototype; | 239 Register scratch = prototype; |
| 256 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); | 240 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
| 257 __ mov(scratch, Operand(esi, offset)); | 241 __ mov(scratch, Operand(esi, offset)); |
| 258 __ mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); | 242 __ mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); |
| 259 __ cmp(Operand(scratch, Context::SlotOffset(index)), function); | 243 __ cmp(Operand(scratch, Context::SlotOffset(index)), function); |
| 260 __ j(not_equal, miss); | 244 __ j(not_equal, miss); |
| 261 | 245 |
| 262 // Load its initial map. The global functions all have initial maps. | 246 // Load its initial map. The global functions all have initial maps. |
| 263 __ Move(prototype, Immediate(Handle<Map>(function->initial_map()))); | 247 __ Move(prototype, Immediate(Handle<Map>(function->initial_map()))); |
| 264 // Load the prototype from the initial map. | 248 // Load the prototype from the initial map. |
| 265 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 249 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
| 266 } | 250 } |
| 267 | 251 |
| 268 | 252 |
| 269 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 253 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
| 270 Register receiver, | 254 MacroAssembler* masm, Register receiver, Register scratch1, |
| 271 Register scratch, | 255 Register scratch2, Label* miss_label) { |
| 272 Label* miss_label) { | |
| 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 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | |
| 278 __ j(not_equal, miss_label); | |
| 279 | |
| 280 // Load length directly from the JS array. | |
| 281 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); | |
| 282 __ ret(0); | |
| 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); | 256 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 292 __ mov(eax, scratch1); | 257 __ mov(eax, scratch1); |
| 293 __ ret(0); | 258 __ ret(0); |
| 294 } | 259 } |
| 295 | 260 |
| 296 | 261 |
| 297 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | |
| 298 Register dst, | |
| 299 Register src, | |
| 300 bool inobject, | |
| 301 int index, | |
| 302 Representation representation) { | |
| 303 ASSERT(!representation.IsDouble()); | |
| 304 int offset = index * kPointerSize; | |
| 305 if (!inobject) { | |
| 306 // Calculate the offset into the properties array. | |
| 307 offset = offset + FixedArray::kHeaderSize; | |
| 308 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | |
| 309 src = dst; | |
| 310 } | |
| 311 __ mov(dst, FieldOperand(src, offset)); | |
| 312 } | |
| 313 | |
| 314 | |
| 315 static void PushInterceptorArguments(MacroAssembler* masm, | 262 static void PushInterceptorArguments(MacroAssembler* masm, |
| 316 Register receiver, | 263 Register receiver, |
| 317 Register holder, | 264 Register holder, |
| 318 Register name, | 265 Register name, |
| 319 Handle<JSObject> holder_obj) { | 266 Handle<JSObject> holder_obj) { |
| 320 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 267 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
| 321 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 268 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
| 322 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 269 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
| 323 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 270 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
| 324 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 271 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 344 __ CallExternalReference( | 291 __ CallExternalReference( |
| 345 ExternalReference(IC_Utility(id), masm->isolate()), | 292 ExternalReference(IC_Utility(id), masm->isolate()), |
| 346 StubCache::kInterceptorArgsLength); | 293 StubCache::kInterceptorArgsLength); |
| 347 } | 294 } |
| 348 | 295 |
| 349 | 296 |
| 350 // Generate call to api function. | 297 // Generate call to api function. |
| 351 // This function uses push() to generate smaller, faster code than | 298 // This function uses push() to generate smaller, faster code than |
| 352 // the version above. It is an optimization that should will be removed | 299 // the version above. It is an optimization that should will be removed |
| 353 // when api call ICs are generated in hydrogen. | 300 // when api call ICs are generated in hydrogen. |
| 354 void StubCompiler::GenerateFastApiCall(MacroAssembler* masm, | 301 void PropertyHandlerCompiler::GenerateFastApiCall( |
| 355 const CallOptimization& optimization, | 302 MacroAssembler* masm, const CallOptimization& optimization, |
| 356 Handle<Map> receiver_map, | 303 Handle<Map> receiver_map, Register receiver, Register scratch_in, |
| 357 Register receiver, | 304 bool is_store, int argc, Register* values) { |
| 358 Register scratch_in, | |
| 359 bool is_store, | |
| 360 int argc, | |
| 361 Register* values) { | |
| 362 // Copy return value. | 305 // Copy return value. |
| 363 __ pop(scratch_in); | 306 __ pop(scratch_in); |
| 364 // receiver | 307 // receiver |
| 365 __ push(receiver); | 308 __ push(receiver); |
| 366 // Write the arguments to stack frame. | 309 // Write the arguments to stack frame. |
| 367 for (int i = 0; i < argc; i++) { | 310 for (int i = 0; i < argc; i++) { |
| 368 Register arg = values[argc-1-i]; | 311 Register arg = values[argc-1-i]; |
| 369 ASSERT(!receiver.is(arg)); | 312 ASSERT(!receiver.is(arg)); |
| 370 ASSERT(!scratch_in.is(arg)); | 313 ASSERT(!scratch_in.is(arg)); |
| 371 __ push(arg); | 314 __ push(arg); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 // Put api_function_address in place. | 364 // Put api_function_address in place. |
| 422 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 365 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
| 423 __ mov(api_function_address, Immediate(function_address)); | 366 __ mov(api_function_address, Immediate(function_address)); |
| 424 | 367 |
| 425 // Jump to stub. | 368 // Jump to stub. |
| 426 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 369 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
| 427 __ TailCallStub(&stub); | 370 __ TailCallStub(&stub); |
| 428 } | 371 } |
| 429 | 372 |
| 430 | 373 |
| 431 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 374 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 432 Label* label, | 375 Label* label, |
| 433 Handle<Name> name) { | 376 Handle<Name> name) { |
| 434 if (!label->is_unused()) { | 377 if (!label->is_unused()) { |
| 435 __ bind(label); | 378 __ bind(label); |
| 436 __ mov(this->name(), Immediate(name)); | 379 __ mov(this->name(), Immediate(name)); |
| 437 } | 380 } |
| 438 } | 381 } |
| 439 | 382 |
| 440 | 383 |
| 441 // Generate code to check that a global property cell is empty. Create | 384 // Generate code to check that a global property cell is empty. Create |
| 442 // the property cell at compilation time if no cell exists for the | 385 // the property cell at compilation time if no cell exists for the |
| 443 // property. | 386 // property. |
| 444 void StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm, | 387 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
| 445 Handle<JSGlobalObject> global, | 388 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
| 446 Handle<Name> name, | 389 Register scratch, Label* miss) { |
| 447 Register scratch, | |
| 448 Label* miss) { | |
| 449 Handle<PropertyCell> cell = | 390 Handle<PropertyCell> cell = |
| 450 JSGlobalObject::EnsurePropertyCell(global, name); | 391 JSGlobalObject::EnsurePropertyCell(global, name); |
| 451 ASSERT(cell->value()->IsTheHole()); | 392 ASSERT(cell->value()->IsTheHole()); |
| 452 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); | 393 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); |
| 453 if (masm->serializer_enabled()) { | 394 if (masm->serializer_enabled()) { |
| 454 __ mov(scratch, Immediate(cell)); | 395 __ mov(scratch, Immediate(cell)); |
| 455 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 396 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |
| 456 Immediate(the_hole)); | 397 Immediate(the_hole)); |
| 457 } else { | 398 } else { |
| 458 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); | 399 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); |
| 459 } | 400 } |
| 460 __ j(not_equal, miss); | 401 __ j(not_equal, miss); |
| 461 } | 402 } |
| 462 | 403 |
| 463 | 404 |
| 464 void StoreStubCompiler::GenerateNegativeHolderLookup( | 405 void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( |
| 465 MacroAssembler* masm, | 406 MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg, |
| 466 Handle<JSObject> holder, | 407 Handle<Name> name, Label* miss) { |
| 467 Register holder_reg, | |
| 468 Handle<Name> name, | |
| 469 Label* miss) { | |
| 470 if (holder->IsJSGlobalObject()) { | 408 if (holder->IsJSGlobalObject()) { |
| 471 GenerateCheckPropertyCell( | 409 GenerateCheckPropertyCell( |
| 472 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); | 410 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); |
| 473 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 411 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 474 GenerateDictionaryNegativeLookup( | 412 GenerateDictionaryNegativeLookup( |
| 475 masm, miss, holder_reg, name, scratch1(), scratch2()); | 413 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 476 } | 414 } |
| 477 } | 415 } |
| 478 | 416 |
| 479 | 417 |
| 480 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 418 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
| 481 // store is successful. | 419 // store is successful. |
| 482 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 420 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
| 483 Handle<JSObject> object, | 421 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
| 484 LookupResult* lookup, | 422 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
| 485 Handle<Map> transition, | 423 Register storage_reg, Register value_reg, Register scratch1, |
| 486 Handle<Name> name, | 424 Register scratch2, Register unused, Label* miss_label, Label* slow) { |
| 487 Register receiver_reg, | |
| 488 Register storage_reg, | |
| 489 Register value_reg, | |
| 490 Register scratch1, | |
| 491 Register scratch2, | |
| 492 Register unused, | |
| 493 Label* miss_label, | |
| 494 Label* slow) { | |
| 495 int descriptor = transition->LastAdded(); | 425 int descriptor = transition->LastAdded(); |
| 496 DescriptorArray* descriptors = transition->instance_descriptors(); | 426 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 497 PropertyDetails details = descriptors->GetDetails(descriptor); | 427 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 498 Representation representation = details.representation(); | 428 Representation representation = details.representation(); |
| 499 ASSERT(!representation.IsNone()); | 429 ASSERT(!representation.IsNone()); |
| 500 | 430 |
| 501 if (details.type() == CONSTANT) { | 431 if (details.type() == CONSTANT) { |
| 502 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 432 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
| 503 __ CmpObject(value_reg, constant); | 433 __ CmpObject(value_reg, constant); |
| 504 __ j(not_equal, miss_label); | 434 __ j(not_equal, miss_label); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 } | 570 } |
| 641 | 571 |
| 642 // Return the value (register eax). | 572 // Return the value (register eax). |
| 643 ASSERT(value_reg.is(eax)); | 573 ASSERT(value_reg.is(eax)); |
| 644 __ ret(0); | 574 __ ret(0); |
| 645 } | 575 } |
| 646 | 576 |
| 647 | 577 |
| 648 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 578 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 649 // but may be destroyed if store is successful. | 579 // but may be destroyed if store is successful. |
| 650 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 580 void NamedStoreHandlerCompiler::GenerateStoreField( |
| 651 Handle<JSObject> object, | 581 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
| 652 LookupResult* lookup, | 582 Register receiver_reg, Register name_reg, Register value_reg, |
| 653 Register receiver_reg, | 583 Register scratch1, Register scratch2, Label* miss_label) { |
| 654 Register name_reg, | |
| 655 Register value_reg, | |
| 656 Register scratch1, | |
| 657 Register scratch2, | |
| 658 Label* miss_label) { | |
| 659 // Stub never generated for non-global objects that require access | 584 // Stub never generated for non-global objects that require access |
| 660 // checks. | 585 // checks. |
| 661 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 586 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 662 | 587 |
| 663 FieldIndex index = lookup->GetFieldIndex(); | 588 FieldIndex index = lookup->GetFieldIndex(); |
| 664 | 589 |
| 665 Representation representation = lookup->representation(); | 590 Representation representation = lookup->representation(); |
| 666 ASSERT(!representation.IsNone()); | 591 ASSERT(!representation.IsNone()); |
| 667 if (representation.IsSmi()) { | 592 if (representation.IsSmi()) { |
| 668 __ JumpIfNotSmi(value_reg, miss_label); | 593 __ JumpIfNotSmi(value_reg, miss_label); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 smi_check); | 675 smi_check); |
| 751 } | 676 } |
| 752 } | 677 } |
| 753 | 678 |
| 754 // Return the value (register eax). | 679 // Return the value (register eax). |
| 755 ASSERT(value_reg.is(eax)); | 680 ASSERT(value_reg.is(eax)); |
| 756 __ ret(0); | 681 __ ret(0); |
| 757 } | 682 } |
| 758 | 683 |
| 759 | 684 |
| 760 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 685 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
| 686 Handle<Code> code) { |
| 761 __ jmp(code, RelocInfo::CODE_TARGET); | 687 __ jmp(code, RelocInfo::CODE_TARGET); |
| 762 } | 688 } |
| 763 | 689 |
| 764 | 690 |
| 765 #undef __ | 691 #undef __ |
| 766 #define __ ACCESS_MASM(masm()) | 692 #define __ ACCESS_MASM(masm()) |
| 767 | 693 |
| 768 | 694 |
| 769 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 695 Register PropertyHandlerCompiler::CheckPrototypes( |
| 770 Register object_reg, | 696 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, |
| 771 Handle<JSObject> holder, | 697 Register holder_reg, Register scratch1, Register scratch2, |
| 772 Register holder_reg, | 698 Handle<Name> name, Label* miss, PrototypeCheckType check) { |
| 773 Register scratch1, | |
| 774 Register scratch2, | |
| 775 Handle<Name> name, | |
| 776 Label* miss, | |
| 777 PrototypeCheckType check) { | |
| 778 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 699 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 779 | 700 |
| 780 // Make sure there's no overlap between holder and object registers. | 701 // Make sure there's no overlap between holder and object registers. |
| 781 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 702 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 782 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 703 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 783 && !scratch2.is(scratch1)); | 704 && !scratch2.is(scratch1)); |
| 784 | 705 |
| 785 // Keep track of the current object in register reg. | 706 // Keep track of the current object in register reg. |
| 786 Register reg = object_reg; | 707 Register reg = object_reg; |
| 787 int depth = 0; | 708 int depth = 0; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 !current_map->is_access_check_needed()); | 795 !current_map->is_access_check_needed()); |
| 875 if (current_map->IsJSGlobalProxyMap()) { | 796 if (current_map->IsJSGlobalProxyMap()) { |
| 876 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 797 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
| 877 } | 798 } |
| 878 | 799 |
| 879 // Return the register containing the holder. | 800 // Return the register containing the holder. |
| 880 return reg; | 801 return reg; |
| 881 } | 802 } |
| 882 | 803 |
| 883 | 804 |
| 884 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 805 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
| 885 if (!miss->is_unused()) { | 806 if (!miss->is_unused()) { |
| 886 Label success; | 807 Label success; |
| 887 __ jmp(&success); | 808 __ jmp(&success); |
| 888 __ bind(miss); | 809 __ bind(miss); |
| 889 TailCallBuiltin(masm(), MissBuiltin(kind())); | 810 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 890 __ bind(&success); | 811 __ bind(&success); |
| 891 } | 812 } |
| 892 } | 813 } |
| 893 | 814 |
| 894 | 815 |
| 895 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 816 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
| 896 if (!miss->is_unused()) { | 817 if (!miss->is_unused()) { |
| 897 Label success; | 818 Label success; |
| 898 __ jmp(&success); | 819 __ jmp(&success); |
| 899 GenerateRestoreName(masm(), miss, name); | 820 GenerateRestoreName(masm(), miss, name); |
| 900 TailCallBuiltin(masm(), MissBuiltin(kind())); | 821 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 901 __ bind(&success); | 822 __ bind(&success); |
| 902 } | 823 } |
| 903 } | 824 } |
| 904 | 825 |
| 905 | 826 |
| 906 Register LoadStubCompiler::CallbackHandlerFrontend( | 827 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
| 907 Handle<HeapType> type, | 828 Register object_reg, |
| 908 Register object_reg, | 829 Handle<JSObject> holder, |
| 909 Handle<JSObject> holder, | 830 Handle<Name> name, |
| 910 Handle<Name> name, | 831 Handle<Object> callback) { |
| 911 Handle<Object> callback) { | |
| 912 Label miss; | 832 Label miss; |
| 913 | 833 |
| 914 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 834 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); |
| 915 | 835 |
| 916 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 836 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 917 ASSERT(!reg.is(scratch2())); | 837 ASSERT(!reg.is(scratch2())); |
| 918 ASSERT(!reg.is(scratch3())); | 838 ASSERT(!reg.is(scratch3())); |
| 919 Register dictionary = scratch1(); | 839 Register dictionary = scratch1(); |
| 920 bool must_preserve_dictionary_reg = reg.is(dictionary); | 840 bool must_preserve_dictionary_reg = reg.is(dictionary); |
| 921 | 841 |
| 922 // Load the properties dictionary. | 842 // Load the properties dictionary. |
| 923 if (must_preserve_dictionary_reg) { | 843 if (must_preserve_dictionary_reg) { |
| 924 __ push(dictionary); | 844 __ push(dictionary); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 950 const int kValueOffset = kElementsStartOffset + kPointerSize; | 870 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 951 __ mov(scratch3(), | 871 __ mov(scratch3(), |
| 952 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); | 872 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); |
| 953 if (must_preserve_dictionary_reg) { | 873 if (must_preserve_dictionary_reg) { |
| 954 __ pop(dictionary); | 874 __ pop(dictionary); |
| 955 } | 875 } |
| 956 __ cmp(scratch3(), callback); | 876 __ cmp(scratch3(), callback); |
| 957 __ j(not_equal, &miss); | 877 __ j(not_equal, &miss); |
| 958 } | 878 } |
| 959 | 879 |
| 960 HandlerFrontendFooter(name, &miss); | 880 FrontendFooter(name, &miss); |
| 961 return reg; | 881 return reg; |
| 962 } | 882 } |
| 963 | 883 |
| 964 | 884 |
| 965 void LoadStubCompiler::GenerateLoadField(Register reg, | 885 void NamedLoadHandlerCompiler::GenerateLoadField( |
| 966 Handle<JSObject> holder, | 886 Register reg, Handle<JSObject> holder, FieldIndex field, |
| 967 FieldIndex field, | 887 Representation representation) { |
| 968 Representation representation) { | |
| 969 if (!reg.is(receiver())) __ mov(receiver(), reg); | 888 if (!reg.is(receiver())) __ mov(receiver(), reg); |
| 970 LoadFieldStub stub(isolate(), field); | 889 LoadFieldStub stub(isolate(), field); |
| 971 GenerateTailCall(masm(), stub.GetCode()); | 890 GenerateTailCall(masm(), stub.GetCode()); |
| 972 } | 891 } |
| 973 | 892 |
| 974 | 893 |
| 975 void LoadStubCompiler::GenerateLoadCallback( | 894 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
| 976 Register reg, | 895 Register reg, Handle<ExecutableAccessorInfo> callback) { |
| 977 Handle<ExecutableAccessorInfo> callback) { | |
| 978 // Insert additional parameters into the stack frame above return address. | 896 // Insert additional parameters into the stack frame above return address. |
| 979 ASSERT(!scratch3().is(reg)); | 897 ASSERT(!scratch3().is(reg)); |
| 980 __ pop(scratch3()); // Get return address to place it below. | 898 __ pop(scratch3()); // Get return address to place it below. |
| 981 | 899 |
| 982 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 900 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
| 983 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 901 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
| 984 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 902 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
| 985 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 903 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
| 986 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 904 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
| 987 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 905 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1011 // Abi for CallApiGetter | 929 // Abi for CallApiGetter |
| 1012 Register getter_address = edx; | 930 Register getter_address = edx; |
| 1013 Address function_address = v8::ToCData<Address>(callback->getter()); | 931 Address function_address = v8::ToCData<Address>(callback->getter()); |
| 1014 __ mov(getter_address, Immediate(function_address)); | 932 __ mov(getter_address, Immediate(function_address)); |
| 1015 | 933 |
| 1016 CallApiGetterStub stub(isolate()); | 934 CallApiGetterStub stub(isolate()); |
| 1017 __ TailCallStub(&stub); | 935 __ TailCallStub(&stub); |
| 1018 } | 936 } |
| 1019 | 937 |
| 1020 | 938 |
| 1021 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 939 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 1022 // Return the constant value. | 940 // Return the constant value. |
| 1023 __ LoadObject(eax, value); | 941 __ LoadObject(eax, value); |
| 1024 __ ret(0); | 942 __ ret(0); |
| 1025 } | 943 } |
| 1026 | 944 |
| 1027 | 945 |
| 1028 void LoadStubCompiler::GenerateLoadInterceptor( | 946 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
| 1029 Register holder_reg, | 947 Register holder_reg, Handle<Object> object, |
| 1030 Handle<Object> object, | 948 Handle<JSObject> interceptor_holder, LookupResult* lookup, |
| 1031 Handle<JSObject> interceptor_holder, | |
| 1032 LookupResult* lookup, | |
| 1033 Handle<Name> name) { | 949 Handle<Name> name) { |
| 1034 ASSERT(interceptor_holder->HasNamedInterceptor()); | 950 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1035 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 951 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1036 | 952 |
| 1037 // So far the most popular follow ups for interceptor loads are FIELD | 953 // So far the most popular follow ups for interceptor loads are FIELD |
| 1038 // and CALLBACKS, so inline only them, other cases may be added | 954 // and CALLBACKS, so inline only them, other cases may be added |
| 1039 // later. | 955 // later. |
| 1040 bool compile_followup_inline = false; | 956 bool compile_followup_inline = false; |
| 1041 if (lookup->IsFound() && lookup->IsCacheable()) { | 957 if (lookup->IsFound() && lookup->IsCacheable()) { |
| 1042 if (lookup->IsField()) { | 958 if (lookup->IsField()) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 __ push(scratch2()); // restore old return address | 1033 __ push(scratch2()); // restore old return address |
| 1118 | 1034 |
| 1119 ExternalReference ref = | 1035 ExternalReference ref = |
| 1120 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), | 1036 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), |
| 1121 isolate()); | 1037 isolate()); |
| 1122 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); | 1038 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
| 1123 } | 1039 } |
| 1124 } | 1040 } |
| 1125 | 1041 |
| 1126 | 1042 |
| 1127 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1043 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 1128 Handle<JSObject> object, | 1044 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
| 1129 Handle<JSObject> holder, | |
| 1130 Handle<Name> name, | |
| 1131 Handle<ExecutableAccessorInfo> callback) { | 1045 Handle<ExecutableAccessorInfo> callback) { |
| 1132 Register holder_reg = HandlerFrontend( | 1046 Register holder_reg = |
| 1133 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | 1047 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
| 1134 | 1048 |
| 1135 __ pop(scratch1()); // remove the return address | 1049 __ pop(scratch1()); // remove the return address |
| 1136 __ push(receiver()); | 1050 __ push(receiver()); |
| 1137 __ push(holder_reg); | 1051 __ push(holder_reg); |
| 1138 __ Push(callback); | 1052 __ Push(callback); |
| 1139 __ Push(name); | 1053 __ Push(name); |
| 1140 __ push(value()); | 1054 __ push(value()); |
| 1141 __ push(scratch1()); // restore return address | 1055 __ push(scratch1()); // restore return address |
| 1142 | 1056 |
| 1143 // Do tail-call to the runtime system. | 1057 // Do tail-call to the runtime system. |
| 1144 ExternalReference store_callback_property = | 1058 ExternalReference store_callback_property = |
| 1145 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1059 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 1146 __ TailCallExternalReference(store_callback_property, 5, 1); | 1060 __ TailCallExternalReference(store_callback_property, 5, 1); |
| 1147 | 1061 |
| 1148 // Return the generated code. | 1062 // Return the generated code. |
| 1149 return GetCode(kind(), Code::FAST, name); | 1063 return GetCode(kind(), Code::FAST, name); |
| 1150 } | 1064 } |
| 1151 | 1065 |
| 1152 | 1066 |
| 1153 #undef __ | 1067 #undef __ |
| 1154 #define __ ACCESS_MASM(masm) | 1068 #define __ ACCESS_MASM(masm) |
| 1155 | 1069 |
| 1156 | 1070 |
| 1157 void StoreStubCompiler::GenerateStoreViaSetter( | 1071 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
| 1158 MacroAssembler* masm, | 1072 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 1159 Handle<HeapType> type, | |
| 1160 Register receiver, | |
| 1161 Handle<JSFunction> setter) { | 1073 Handle<JSFunction> setter) { |
| 1162 // ----------- S t a t e ------------- | 1074 // ----------- S t a t e ------------- |
| 1163 // -- esp[0] : return address | 1075 // -- esp[0] : return address |
| 1164 // ----------------------------------- | 1076 // ----------------------------------- |
| 1165 { | 1077 { |
| 1166 FrameScope scope(masm, StackFrame::INTERNAL); | 1078 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1167 | 1079 |
| 1168 // Save value register, so we can restore it later. | 1080 // Save value register, so we can restore it later. |
| 1169 __ push(value()); | 1081 __ push(value()); |
| 1170 | 1082 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1194 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1106 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1195 } | 1107 } |
| 1196 __ ret(0); | 1108 __ ret(0); |
| 1197 } | 1109 } |
| 1198 | 1110 |
| 1199 | 1111 |
| 1200 #undef __ | 1112 #undef __ |
| 1201 #define __ ACCESS_MASM(masm()) | 1113 #define __ ACCESS_MASM(masm()) |
| 1202 | 1114 |
| 1203 | 1115 |
| 1204 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 1116 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
| 1205 Handle<JSObject> object, | 1117 Handle<JSObject> object, Handle<Name> name) { |
| 1206 Handle<Name> name) { | |
| 1207 __ pop(scratch1()); // remove the return address | 1118 __ pop(scratch1()); // remove the return address |
| 1208 __ push(receiver()); | 1119 __ push(receiver()); |
| 1209 __ push(this->name()); | 1120 __ push(this->name()); |
| 1210 __ push(value()); | 1121 __ push(value()); |
| 1211 __ push(scratch1()); // restore return address | 1122 __ push(scratch1()); // restore return address |
| 1212 | 1123 |
| 1213 // Do tail-call to the runtime system. | 1124 // Do tail-call to the runtime system. |
| 1214 ExternalReference store_ic_property = | 1125 ExternalReference store_ic_property = |
| 1215 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 1126 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 1216 __ TailCallExternalReference(store_ic_property, 3, 1); | 1127 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 1217 | 1128 |
| 1218 // Return the generated code. | 1129 // Return the generated code. |
| 1219 return GetCode(kind(), Code::FAST, name); | 1130 return GetCode(kind(), Code::FAST, name); |
| 1220 } | 1131 } |
| 1221 | 1132 |
| 1222 | 1133 |
| 1223 void StoreStubCompiler::GenerateStoreArrayLength() { | 1134 void NamedStoreHandlerCompiler::GenerateStoreArrayLength() { |
| 1224 // Prepare tail call to StoreIC_ArrayLength. | 1135 // Prepare tail call to StoreIC_ArrayLength. |
| 1225 __ pop(scratch1()); // remove the return address | 1136 __ pop(scratch1()); // remove the return address |
| 1226 __ push(receiver()); | 1137 __ push(receiver()); |
| 1227 __ push(value()); | 1138 __ push(value()); |
| 1228 __ push(scratch1()); // restore return address | 1139 __ push(scratch1()); // restore return address |
| 1229 | 1140 |
| 1230 ExternalReference ref = | 1141 ExternalReference ref = |
| 1231 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), | 1142 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), |
| 1232 masm()->isolate()); | 1143 masm()->isolate()); |
| 1233 __ TailCallExternalReference(ref, 2, 1); | 1144 __ TailCallExternalReference(ref, 2, 1); |
| 1234 } | 1145 } |
| 1235 | 1146 |
| 1236 | 1147 |
| 1237 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 1148 Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( |
| 1238 MapHandleList* receiver_maps, | 1149 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
| 1239 CodeHandleList* handler_stubs, | |
| 1240 MapHandleList* transitioned_maps) { | 1150 MapHandleList* transitioned_maps) { |
| 1241 Label miss; | 1151 Label miss; |
| 1242 __ JumpIfSmi(receiver(), &miss, Label::kNear); | 1152 __ JumpIfSmi(receiver(), &miss, Label::kNear); |
| 1243 __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); | 1153 __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); |
| 1244 for (int i = 0; i < receiver_maps->length(); ++i) { | 1154 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 1245 __ cmp(scratch1(), receiver_maps->at(i)); | 1155 __ cmp(scratch1(), receiver_maps->at(i)); |
| 1246 if (transitioned_maps->at(i).is_null()) { | 1156 if (transitioned_maps->at(i).is_null()) { |
| 1247 __ j(equal, handler_stubs->at(i)); | 1157 __ j(equal, handler_stubs->at(i)); |
| 1248 } else { | 1158 } else { |
| 1249 Label next_map; | 1159 Label next_map; |
| 1250 __ j(not_equal, &next_map, Label::kNear); | 1160 __ j(not_equal, &next_map, Label::kNear); |
| 1251 __ mov(transition_map(), Immediate(transitioned_maps->at(i))); | 1161 __ mov(transition_map(), Immediate(transitioned_maps->at(i))); |
| 1252 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 1162 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
| 1253 __ bind(&next_map); | 1163 __ bind(&next_map); |
| 1254 } | 1164 } |
| 1255 } | 1165 } |
| 1256 __ bind(&miss); | 1166 __ bind(&miss); |
| 1257 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1167 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1258 | 1168 |
| 1259 // Return the generated code. | 1169 // Return the generated code. |
| 1260 return GetICCode( | 1170 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 1261 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
| 1262 } | 1171 } |
| 1263 | 1172 |
| 1264 | 1173 |
| 1265 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, | 1174 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
| 1266 Handle<JSObject> last, | 1175 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { |
| 1267 Handle<Name> name) { | 1176 NonexistentFrontend(type, last, name); |
| 1268 NonexistentHandlerFrontend(type, last, name); | |
| 1269 | 1177 |
| 1270 // Return undefined if maps of the full prototype chain are still the | 1178 // Return undefined if maps of the full prototype chain are still the |
| 1271 // same and no global property with this name contains a value. | 1179 // same and no global property with this name contains a value. |
| 1272 __ mov(eax, isolate()->factory()->undefined_value()); | 1180 __ mov(eax, isolate()->factory()->undefined_value()); |
| 1273 __ ret(0); | 1181 __ ret(0); |
| 1274 | 1182 |
| 1275 // Return the generated code. | 1183 // Return the generated code. |
| 1276 return GetCode(kind(), Code::FAST, name); | 1184 return GetCode(kind(), Code::FAST, name); |
| 1277 } | 1185 } |
| 1278 | 1186 |
| 1279 | 1187 |
| 1280 Register* LoadStubCompiler::registers() { | 1188 Register* PropertyAccessCompiler::load_calling_convention() { |
| 1281 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1189 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
| 1282 Register receiver = LoadIC::ReceiverRegister(); | 1190 Register receiver = LoadIC::ReceiverRegister(); |
| 1283 Register name = LoadIC::NameRegister(); | 1191 Register name = LoadIC::NameRegister(); |
| 1284 static Register registers[] = { receiver, name, ebx, eax, edi, no_reg }; | |
| 1285 return registers; | |
| 1286 } | |
| 1287 | |
| 1288 | |
| 1289 Register* KeyedLoadStubCompiler::registers() { | |
| 1290 // receiver, name, scratch1, scratch2, scratch3, scratch4. | |
| 1291 Register receiver = LoadIC::ReceiverRegister(); | |
| 1292 Register name = LoadIC::NameRegister(); | |
| 1293 static Register registers[] = { receiver, name, ebx, eax, edi, no_reg }; | 1192 static Register registers[] = { receiver, name, ebx, eax, edi, no_reg }; |
| 1294 return registers; | 1193 return registers; |
| 1295 } | 1194 } |
| 1296 | 1195 |
| 1297 | 1196 |
| 1298 Register StoreStubCompiler::value() { | 1197 Register* PropertyAccessCompiler::store_calling_convention() { |
| 1299 return StoreIC::ValueRegister(); | |
| 1300 } | |
| 1301 | |
| 1302 | |
| 1303 Register* StoreStubCompiler::registers() { | |
| 1304 // receiver, name, scratch1, scratch2, scratch3. | 1198 // receiver, name, scratch1, scratch2, scratch3. |
| 1305 Register receiver = StoreIC::ReceiverRegister(); | 1199 Register receiver = StoreIC::ReceiverRegister(); |
| 1306 Register name = StoreIC::NameRegister(); | 1200 Register name = StoreIC::NameRegister(); |
| 1307 static Register registers[] = { receiver, name, ebx, edi, no_reg }; | 1201 static Register registers[] = { receiver, name, ebx, edi, no_reg }; |
| 1308 return registers; | 1202 return registers; |
| 1309 } | 1203 } |
| 1310 | 1204 |
| 1311 | 1205 |
| 1312 Register* KeyedStoreStubCompiler::registers() { | 1206 Register* PropertyAccessCompiler::keyed_store_calling_convention() { |
| 1313 // receiver, name, scratch1/map, scratch2, scratch3. | 1207 // receiver, name, scratch1/map, scratch2, scratch3. |
| 1314 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1208 Register receiver = KeyedStoreIC::ReceiverRegister(); |
| 1315 Register name = KeyedStoreIC::NameRegister(); | 1209 Register name = KeyedStoreIC::NameRegister(); |
| 1316 Register map = KeyedStoreIC::MapRegister(); | 1210 Register map = KeyedStoreIC::MapRegister(); |
| 1317 static Register registers[] = { receiver, name, map, edi, no_reg }; | 1211 static Register registers[] = { receiver, name, map, edi, no_reg }; |
| 1318 return registers; | 1212 return registers; |
| 1319 } | 1213 } |
| 1320 | 1214 |
| 1321 | 1215 |
| 1216 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1217 |
| 1218 |
| 1322 #undef __ | 1219 #undef __ |
| 1323 #define __ ACCESS_MASM(masm) | 1220 #define __ ACCESS_MASM(masm) |
| 1324 | 1221 |
| 1325 | 1222 |
| 1326 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1223 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
| 1327 Handle<HeapType> type, | 1224 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 1328 Register receiver, | 1225 Handle<JSFunction> getter) { |
| 1329 Handle<JSFunction> getter) { | |
| 1330 { | 1226 { |
| 1331 FrameScope scope(masm, StackFrame::INTERNAL); | 1227 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1332 | 1228 |
| 1333 if (!getter.is_null()) { | 1229 if (!getter.is_null()) { |
| 1334 // Call the JavaScript getter with the receiver on the stack. | 1230 // Call the JavaScript getter with the receiver on the stack. |
| 1335 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 1231 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 1336 // Swap in the global receiver. | 1232 // Swap in the global receiver. |
| 1337 __ mov(receiver, | 1233 __ mov(receiver, |
| 1338 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 1234 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
| 1339 } | 1235 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1352 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1248 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1353 } | 1249 } |
| 1354 __ ret(0); | 1250 __ ret(0); |
| 1355 } | 1251 } |
| 1356 | 1252 |
| 1357 | 1253 |
| 1358 #undef __ | 1254 #undef __ |
| 1359 #define __ ACCESS_MASM(masm()) | 1255 #define __ ACCESS_MASM(masm()) |
| 1360 | 1256 |
| 1361 | 1257 |
| 1362 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 1258 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| 1363 Handle<HeapType> type, | 1259 Handle<HeapType> type, Handle<GlobalObject> global, |
| 1364 Handle<GlobalObject> global, | 1260 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
| 1365 Handle<PropertyCell> cell, | |
| 1366 Handle<Name> name, | |
| 1367 bool is_dont_delete) { | |
| 1368 Label miss; | 1261 Label miss; |
| 1369 | 1262 |
| 1370 HandlerFrontendHeader(type, receiver(), global, name, &miss); | 1263 FrontendHeader(type, receiver(), global, name, &miss); |
| 1371 // Get the value from the cell. | 1264 // Get the value from the cell. |
| 1372 if (masm()->serializer_enabled()) { | 1265 if (masm()->serializer_enabled()) { |
| 1373 __ mov(eax, Immediate(cell)); | 1266 __ mov(eax, Immediate(cell)); |
| 1374 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); | 1267 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); |
| 1375 } else { | 1268 } else { |
| 1376 __ mov(eax, Operand::ForCell(cell)); | 1269 __ mov(eax, Operand::ForCell(cell)); |
| 1377 } | 1270 } |
| 1378 | 1271 |
| 1379 // Check for deleted property if property can actually be deleted. | 1272 // Check for deleted property if property can actually be deleted. |
| 1380 if (!is_dont_delete) { | 1273 if (!is_dont_delete) { |
| 1381 __ cmp(eax, factory()->the_hole_value()); | 1274 __ cmp(eax, factory()->the_hole_value()); |
| 1382 __ j(equal, &miss); | 1275 __ j(equal, &miss); |
| 1383 } else if (FLAG_debug_code) { | 1276 } else if (FLAG_debug_code) { |
| 1384 __ cmp(eax, factory()->the_hole_value()); | 1277 __ cmp(eax, factory()->the_hole_value()); |
| 1385 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); | 1278 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); |
| 1386 } | 1279 } |
| 1387 | 1280 |
| 1388 Counters* counters = isolate()->counters(); | 1281 Counters* counters = isolate()->counters(); |
| 1389 __ IncrementCounter(counters->named_load_global_stub(), 1); | 1282 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 1390 // The code above already loads the result into the return register. | 1283 // The code above already loads the result into the return register. |
| 1391 __ ret(0); | 1284 __ ret(0); |
| 1392 | 1285 |
| 1393 HandlerFrontendFooter(name, &miss); | 1286 FrontendFooter(name, &miss); |
| 1394 | 1287 |
| 1395 // Return the generated code. | 1288 // Return the generated code. |
| 1396 return GetCode(kind(), Code::NORMAL, name); | 1289 return GetCode(kind(), Code::NORMAL, name); |
| 1397 } | 1290 } |
| 1398 | 1291 |
| 1399 | 1292 |
| 1400 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 1293 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
| 1401 TypeHandleList* types, | 1294 CodeHandleList* handlers, |
| 1402 CodeHandleList* handlers, | 1295 Handle<Name> name, |
| 1403 Handle<Name> name, | 1296 Code::StubType type, |
| 1404 Code::StubType type, | 1297 IcCheckType check) { |
| 1405 IcCheckType check) { | |
| 1406 Label miss; | 1298 Label miss; |
| 1407 | 1299 |
| 1408 if (check == PROPERTY && | 1300 if (check == PROPERTY && |
| 1409 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | 1301 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { |
| 1410 __ cmp(this->name(), Immediate(name)); | 1302 __ cmp(this->name(), Immediate(name)); |
| 1411 __ j(not_equal, &miss); | 1303 __ j(not_equal, &miss); |
| 1412 } | 1304 } |
| 1413 | 1305 |
| 1414 Label number_case; | 1306 Label number_case; |
| 1415 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1307 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1436 } | 1328 } |
| 1437 } | 1329 } |
| 1438 ASSERT(number_of_handled_maps != 0); | 1330 ASSERT(number_of_handled_maps != 0); |
| 1439 | 1331 |
| 1440 __ bind(&miss); | 1332 __ bind(&miss); |
| 1441 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1333 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1442 | 1334 |
| 1443 // Return the generated code. | 1335 // Return the generated code. |
| 1444 InlineCacheState state = | 1336 InlineCacheState state = |
| 1445 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 1337 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
| 1446 return GetICCode(kind(), type, name, state); | 1338 return GetCode(kind(), type, name, state); |
| 1447 } | 1339 } |
| 1448 | 1340 |
| 1449 | 1341 |
| 1450 #undef __ | 1342 #undef __ |
| 1451 #define __ ACCESS_MASM(masm) | 1343 #define __ ACCESS_MASM(masm) |
| 1452 | 1344 |
| 1453 | 1345 |
| 1454 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( | 1346 void IndexedHandlerCompiler::GenerateLoadDictionaryElement( |
| 1455 MacroAssembler* masm) { | 1347 MacroAssembler* masm) { |
| 1456 // ----------- S t a t e ------------- | 1348 // ----------- S t a t e ------------- |
| 1457 // -- ecx : key | 1349 // -- ecx : key |
| 1458 // -- edx : receiver | 1350 // -- edx : receiver |
| 1459 // -- esp[0] : return address | 1351 // -- esp[0] : return address |
| 1460 // ----------------------------------- | 1352 // ----------------------------------- |
| 1461 ASSERT(edx.is(LoadIC::ReceiverRegister())); | 1353 ASSERT(edx.is(LoadIC::ReceiverRegister())); |
| 1462 ASSERT(ecx.is(LoadIC::NameRegister())); | 1354 ASSERT(ecx.is(LoadIC::NameRegister())); |
| 1463 Label slow, miss; | 1355 Label slow, miss; |
| 1464 | 1356 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1495 // ----------------------------------- | 1387 // ----------------------------------- |
| 1496 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1388 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1497 } | 1389 } |
| 1498 | 1390 |
| 1499 | 1391 |
| 1500 #undef __ | 1392 #undef __ |
| 1501 | 1393 |
| 1502 } } // namespace v8::internal | 1394 } } // namespace v8::internal |
| 1503 | 1395 |
| 1504 #endif // V8_TARGET_ARCH_X87 | 1396 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |