| 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_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 #endif | 79 #endif |
| 80 | 80 |
| 81 // Jump to the first instruction in the code stub. | 81 // Jump to the first instruction in the code stub. |
| 82 __ addp(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 82 __ addp(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 83 __ jmp(kScratchRegister); | 83 __ jmp(kScratchRegister); |
| 84 | 84 |
| 85 __ bind(&miss); | 85 __ bind(&miss); |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 void StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 89 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
| 90 Label* miss_label, | 90 MacroAssembler* masm, Label* miss_label, Register receiver, |
| 91 Register receiver, | 91 Handle<Name> name, Register scratch0, Register scratch1) { |
| 92 Handle<Name> name, | |
| 93 Register scratch0, | |
| 94 Register scratch1) { | |
| 95 ASSERT(name->IsUniqueName()); | 92 ASSERT(name->IsUniqueName()); |
| 96 ASSERT(!receiver.is(scratch0)); | 93 ASSERT(!receiver.is(scratch0)); |
| 97 Counters* counters = masm->isolate()->counters(); | 94 Counters* counters = masm->isolate()->counters(); |
| 98 __ IncrementCounter(counters->negative_lookups(), 1); | 95 __ IncrementCounter(counters->negative_lookups(), 1); |
| 99 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 96 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 100 | 97 |
| 101 __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); | 98 __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 102 | 99 |
| 103 const int kInterceptorOrAccessCheckNeededMask = | 100 const int kInterceptorOrAccessCheckNeededMask = |
| 104 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 101 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 // Probe the secondary table. | 189 // Probe the secondary table. |
| 193 ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch); | 190 ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch); |
| 194 | 191 |
| 195 // Cache miss: Fall-through and let caller handle the miss by | 192 // Cache miss: Fall-through and let caller handle the miss by |
| 196 // entering the runtime system. | 193 // entering the runtime system. |
| 197 __ bind(&miss); | 194 __ bind(&miss); |
| 198 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 195 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
| 199 } | 196 } |
| 200 | 197 |
| 201 | 198 |
| 202 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 199 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
| 203 int index, | 200 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
| 204 Register prototype) { | |
| 205 // Load the global or builtins object from the current context. | |
| 206 __ movp(prototype, | |
| 207 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
| 208 // Load the native context from the global or builtins object. | |
| 209 __ movp(prototype, | |
| 210 FieldOperand(prototype, GlobalObject::kNativeContextOffset)); | |
| 211 // Load the function from the native context. | |
| 212 __ movp(prototype, Operand(prototype, Context::SlotOffset(index))); | |
| 213 // Load the initial map. The global functions all have initial maps. | |
| 214 __ movp(prototype, | |
| 215 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); | |
| 216 // Load the prototype from the initial map. | |
| 217 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | |
| 218 } | |
| 219 | |
| 220 | |
| 221 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | |
| 222 MacroAssembler* masm, | |
| 223 int index, | |
| 224 Register prototype, | |
| 225 Label* miss) { | |
| 226 Isolate* isolate = masm->isolate(); | 201 Isolate* isolate = masm->isolate(); |
| 227 // Get the global function with the given index. | 202 // Get the global function with the given index. |
| 228 Handle<JSFunction> function( | 203 Handle<JSFunction> function( |
| 229 JSFunction::cast(isolate->native_context()->get(index))); | 204 JSFunction::cast(isolate->native_context()->get(index))); |
| 230 | 205 |
| 231 // Check we're still in the same context. | 206 // Check we're still in the same context. |
| 232 Register scratch = prototype; | 207 Register scratch = prototype; |
| 233 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); | 208 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
| 234 __ movp(scratch, Operand(rsi, offset)); | 209 __ movp(scratch, Operand(rsi, offset)); |
| 235 __ movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); | 210 __ movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); |
| 236 __ Cmp(Operand(scratch, Context::SlotOffset(index)), function); | 211 __ Cmp(Operand(scratch, Context::SlotOffset(index)), function); |
| 237 __ j(not_equal, miss); | 212 __ j(not_equal, miss); |
| 238 | 213 |
| 239 // Load its initial map. The global functions all have initial maps. | 214 // Load its initial map. The global functions all have initial maps. |
| 240 __ Move(prototype, Handle<Map>(function->initial_map())); | 215 __ Move(prototype, Handle<Map>(function->initial_map())); |
| 241 // Load the prototype from the initial map. | 216 // Load the prototype from the initial map. |
| 242 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 217 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
| 243 } | 218 } |
| 244 | 219 |
| 245 | 220 |
| 246 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 221 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
| 247 Register receiver, | 222 MacroAssembler* masm, Register receiver, Register result, Register scratch, |
| 248 Register scratch, | 223 Label* miss_label) { |
| 249 Label* miss_label) { | |
| 250 // Check that the receiver isn't a smi. | |
| 251 __ JumpIfSmi(receiver, miss_label); | |
| 252 | |
| 253 // Check that the object is a JS array. | |
| 254 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | |
| 255 __ j(not_equal, miss_label); | |
| 256 | |
| 257 // Load length directly from the JS array. | |
| 258 __ movp(rax, FieldOperand(receiver, JSArray::kLengthOffset)); | |
| 259 __ ret(0); | |
| 260 } | |
| 261 | |
| 262 | |
| 263 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | |
| 264 Register receiver, | |
| 265 Register result, | |
| 266 Register scratch, | |
| 267 Label* miss_label) { | |
| 268 __ TryGetFunctionPrototype(receiver, result, miss_label); | 224 __ TryGetFunctionPrototype(receiver, result, miss_label); |
| 269 if (!result.is(rax)) __ movp(rax, result); | 225 if (!result.is(rax)) __ movp(rax, result); |
| 270 __ ret(0); | 226 __ ret(0); |
| 271 } | 227 } |
| 272 | 228 |
| 273 | 229 |
| 274 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | |
| 275 Register dst, | |
| 276 Register src, | |
| 277 bool inobject, | |
| 278 int index, | |
| 279 Representation representation) { | |
| 280 ASSERT(!representation.IsDouble()); | |
| 281 int offset = index * kPointerSize; | |
| 282 if (!inobject) { | |
| 283 // Calculate the offset into the properties array. | |
| 284 offset = offset + FixedArray::kHeaderSize; | |
| 285 __ movp(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | |
| 286 src = dst; | |
| 287 } | |
| 288 __ movp(dst, FieldOperand(src, offset)); | |
| 289 } | |
| 290 | |
| 291 | |
| 292 static void PushInterceptorArguments(MacroAssembler* masm, | 230 static void PushInterceptorArguments(MacroAssembler* masm, |
| 293 Register receiver, | 231 Register receiver, |
| 294 Register holder, | 232 Register holder, |
| 295 Register name, | 233 Register name, |
| 296 Handle<JSObject> holder_obj) { | 234 Handle<JSObject> holder_obj) { |
| 297 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 235 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
| 298 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 236 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
| 299 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 237 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
| 300 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 238 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
| 301 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 239 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 317 Handle<JSObject> holder_obj, | 255 Handle<JSObject> holder_obj, |
| 318 IC::UtilityId id) { | 256 IC::UtilityId id) { |
| 319 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 257 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 320 __ CallExternalReference( | 258 __ CallExternalReference( |
| 321 ExternalReference(IC_Utility(id), masm->isolate()), | 259 ExternalReference(IC_Utility(id), masm->isolate()), |
| 322 StubCache::kInterceptorArgsLength); | 260 StubCache::kInterceptorArgsLength); |
| 323 } | 261 } |
| 324 | 262 |
| 325 | 263 |
| 326 // Generate call to api function. | 264 // Generate call to api function. |
| 327 void StubCompiler::GenerateFastApiCall(MacroAssembler* masm, | 265 void PropertyHandlerCompiler::GenerateFastApiCall( |
| 328 const CallOptimization& optimization, | 266 MacroAssembler* masm, const CallOptimization& optimization, |
| 329 Handle<Map> receiver_map, | 267 Handle<Map> receiver_map, Register receiver, Register scratch_in, |
| 330 Register receiver, | 268 bool is_store, int argc, Register* values) { |
| 331 Register scratch_in, | |
| 332 bool is_store, | |
| 333 int argc, | |
| 334 Register* values) { | |
| 335 ASSERT(optimization.is_simple_api_call()); | 269 ASSERT(optimization.is_simple_api_call()); |
| 336 | 270 |
| 337 __ PopReturnAddressTo(scratch_in); | 271 __ PopReturnAddressTo(scratch_in); |
| 338 // receiver | 272 // receiver |
| 339 __ Push(receiver); | 273 __ Push(receiver); |
| 340 // Write the arguments to stack frame. | 274 // Write the arguments to stack frame. |
| 341 for (int i = 0; i < argc; i++) { | 275 for (int i = 0; i < argc; i++) { |
| 342 Register arg = values[argc-1-i]; | 276 Register arg = values[argc-1-i]; |
| 343 ASSERT(!receiver.is(arg)); | 277 ASSERT(!receiver.is(arg)); |
| 344 ASSERT(!scratch_in.is(arg)); | 278 ASSERT(!scratch_in.is(arg)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 329 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
| 396 __ Move( | 330 __ Move( |
| 397 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); | 331 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); |
| 398 | 332 |
| 399 // Jump to stub. | 333 // Jump to stub. |
| 400 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 334 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
| 401 __ TailCallStub(&stub); | 335 __ TailCallStub(&stub); |
| 402 } | 336 } |
| 403 | 337 |
| 404 | 338 |
| 405 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 339 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 406 Label* label, | 340 Label* label, |
| 407 Handle<Name> name) { | 341 Handle<Name> name) { |
| 408 if (!label->is_unused()) { | 342 if (!label->is_unused()) { |
| 409 __ bind(label); | 343 __ bind(label); |
| 410 __ Move(this->name(), name); | 344 __ Move(this->name(), name); |
| 411 } | 345 } |
| 412 } | 346 } |
| 413 | 347 |
| 414 | 348 |
| 415 void StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm, | 349 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
| 416 Handle<JSGlobalObject> global, | 350 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
| 417 Handle<Name> name, | 351 Register scratch, Label* miss) { |
| 418 Register scratch, | |
| 419 Label* miss) { | |
| 420 Handle<PropertyCell> cell = | 352 Handle<PropertyCell> cell = |
| 421 JSGlobalObject::EnsurePropertyCell(global, name); | 353 JSGlobalObject::EnsurePropertyCell(global, name); |
| 422 ASSERT(cell->value()->IsTheHole()); | 354 ASSERT(cell->value()->IsTheHole()); |
| 423 __ Move(scratch, cell); | 355 __ Move(scratch, cell); |
| 424 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), | 356 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), |
| 425 masm->isolate()->factory()->the_hole_value()); | 357 masm->isolate()->factory()->the_hole_value()); |
| 426 __ j(not_equal, miss); | 358 __ j(not_equal, miss); |
| 427 } | 359 } |
| 428 | 360 |
| 429 | 361 |
| 430 void StoreStubCompiler::GenerateNegativeHolderLookup( | 362 void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( |
| 431 MacroAssembler* masm, | 363 MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg, |
| 432 Handle<JSObject> holder, | 364 Handle<Name> name, Label* miss) { |
| 433 Register holder_reg, | |
| 434 Handle<Name> name, | |
| 435 Label* miss) { | |
| 436 if (holder->IsJSGlobalObject()) { | 365 if (holder->IsJSGlobalObject()) { |
| 437 GenerateCheckPropertyCell( | 366 GenerateCheckPropertyCell( |
| 438 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); | 367 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); |
| 439 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 368 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 440 GenerateDictionaryNegativeLookup( | 369 GenerateDictionaryNegativeLookup( |
| 441 masm, miss, holder_reg, name, scratch1(), scratch2()); | 370 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 442 } | 371 } |
| 443 } | 372 } |
| 444 | 373 |
| 445 | 374 |
| 446 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 375 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
| 447 // store is successful. | 376 // store is successful. |
| 448 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 377 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
| 449 Handle<JSObject> object, | 378 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
| 450 LookupResult* lookup, | 379 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
| 451 Handle<Map> transition, | 380 Register storage_reg, Register value_reg, Register scratch1, |
| 452 Handle<Name> name, | 381 Register scratch2, Register unused, Label* miss_label, Label* slow) { |
| 453 Register receiver_reg, | |
| 454 Register storage_reg, | |
| 455 Register value_reg, | |
| 456 Register scratch1, | |
| 457 Register scratch2, | |
| 458 Register unused, | |
| 459 Label* miss_label, | |
| 460 Label* slow) { | |
| 461 int descriptor = transition->LastAdded(); | 382 int descriptor = transition->LastAdded(); |
| 462 DescriptorArray* descriptors = transition->instance_descriptors(); | 383 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 463 PropertyDetails details = descriptors->GetDetails(descriptor); | 384 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 464 Representation representation = details.representation(); | 385 Representation representation = details.representation(); |
| 465 ASSERT(!representation.IsNone()); | 386 ASSERT(!representation.IsNone()); |
| 466 | 387 |
| 467 if (details.type() == CONSTANT) { | 388 if (details.type() == CONSTANT) { |
| 468 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 389 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
| 469 __ Cmp(value_reg, constant); | 390 __ Cmp(value_reg, constant); |
| 470 __ j(not_equal, miss_label); | 391 __ j(not_equal, miss_label); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 } | 519 } |
| 599 | 520 |
| 600 // Return the value (register rax). | 521 // Return the value (register rax). |
| 601 ASSERT(value_reg.is(rax)); | 522 ASSERT(value_reg.is(rax)); |
| 602 __ ret(0); | 523 __ ret(0); |
| 603 } | 524 } |
| 604 | 525 |
| 605 | 526 |
| 606 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 527 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 607 // but may be destroyed if store is successful. | 528 // but may be destroyed if store is successful. |
| 608 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 529 void NamedStoreHandlerCompiler::GenerateStoreField( |
| 609 Handle<JSObject> object, | 530 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
| 610 LookupResult* lookup, | 531 Register receiver_reg, Register name_reg, Register value_reg, |
| 611 Register receiver_reg, | 532 Register scratch1, Register scratch2, Label* miss_label) { |
| 612 Register name_reg, | |
| 613 Register value_reg, | |
| 614 Register scratch1, | |
| 615 Register scratch2, | |
| 616 Label* miss_label) { | |
| 617 // Stub never generated for non-global objects that require access | 533 // Stub never generated for non-global objects that require access |
| 618 // checks. | 534 // checks. |
| 619 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 535 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 620 | 536 |
| 621 FieldIndex index = lookup->GetFieldIndex(); | 537 FieldIndex index = lookup->GetFieldIndex(); |
| 622 | 538 |
| 623 Representation representation = lookup->representation(); | 539 Representation representation = lookup->representation(); |
| 624 ASSERT(!representation.IsNone()); | 540 ASSERT(!representation.IsNone()); |
| 625 if (representation.IsSmi()) { | 541 if (representation.IsSmi()) { |
| 626 __ JumpIfNotSmi(value_reg, miss_label); | 542 __ JumpIfNotSmi(value_reg, miss_label); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 EMIT_REMEMBERED_SET, smi_check); | 616 EMIT_REMEMBERED_SET, smi_check); |
| 701 } | 617 } |
| 702 } | 618 } |
| 703 | 619 |
| 704 // Return the value (register rax). | 620 // Return the value (register rax). |
| 705 ASSERT(value_reg.is(rax)); | 621 ASSERT(value_reg.is(rax)); |
| 706 __ ret(0); | 622 __ ret(0); |
| 707 } | 623 } |
| 708 | 624 |
| 709 | 625 |
| 710 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 626 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
| 627 Handle<Code> code) { |
| 711 __ jmp(code, RelocInfo::CODE_TARGET); | 628 __ jmp(code, RelocInfo::CODE_TARGET); |
| 712 } | 629 } |
| 713 | 630 |
| 714 | 631 |
| 715 #undef __ | 632 #undef __ |
| 716 #define __ ACCESS_MASM((masm())) | 633 #define __ ACCESS_MASM((masm())) |
| 717 | 634 |
| 718 | 635 |
| 719 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 636 Register PropertyHandlerCompiler::CheckPrototypes( |
| 720 Register object_reg, | 637 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, |
| 721 Handle<JSObject> holder, | 638 Register holder_reg, Register scratch1, Register scratch2, |
| 722 Register holder_reg, | 639 Handle<Name> name, Label* miss, PrototypeCheckType check) { |
| 723 Register scratch1, | |
| 724 Register scratch2, | |
| 725 Handle<Name> name, | |
| 726 Label* miss, | |
| 727 PrototypeCheckType check) { | |
| 728 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 640 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 729 | 641 |
| 730 // Make sure there's no overlap between holder and object registers. | 642 // Make sure there's no overlap between holder and object registers. |
| 731 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 643 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 732 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 644 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 733 && !scratch2.is(scratch1)); | 645 && !scratch2.is(scratch1)); |
| 734 | 646 |
| 735 // Keep track of the current object in register reg. On the first | 647 // Keep track of the current object in register reg. On the first |
| 736 // iteration, reg is an alias for object_reg, on later iterations, | 648 // iteration, reg is an alias for object_reg, on later iterations, |
| 737 // it is an alias for holder_reg. | 649 // it is an alias for holder_reg. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 !current_map->is_access_check_needed()); | 737 !current_map->is_access_check_needed()); |
| 826 if (current_map->IsJSGlobalProxyMap()) { | 738 if (current_map->IsJSGlobalProxyMap()) { |
| 827 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 739 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 828 } | 740 } |
| 829 | 741 |
| 830 // Return the register containing the holder. | 742 // Return the register containing the holder. |
| 831 return reg; | 743 return reg; |
| 832 } | 744 } |
| 833 | 745 |
| 834 | 746 |
| 835 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 747 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
| 836 if (!miss->is_unused()) { | 748 if (!miss->is_unused()) { |
| 837 Label success; | 749 Label success; |
| 838 __ jmp(&success); | 750 __ jmp(&success); |
| 839 __ bind(miss); | 751 __ bind(miss); |
| 840 TailCallBuiltin(masm(), MissBuiltin(kind())); | 752 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 841 __ bind(&success); | 753 __ bind(&success); |
| 842 } | 754 } |
| 843 } | 755 } |
| 844 | 756 |
| 845 | 757 |
| 846 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 758 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
| 847 if (!miss->is_unused()) { | 759 if (!miss->is_unused()) { |
| 848 Label success; | 760 Label success; |
| 849 __ jmp(&success); | 761 __ jmp(&success); |
| 850 GenerateRestoreName(masm(), miss, name); | 762 GenerateRestoreName(masm(), miss, name); |
| 851 TailCallBuiltin(masm(), MissBuiltin(kind())); | 763 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 852 __ bind(&success); | 764 __ bind(&success); |
| 853 } | 765 } |
| 854 } | 766 } |
| 855 | 767 |
| 856 | 768 |
| 857 Register LoadStubCompiler::CallbackHandlerFrontend( | 769 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
| 858 Handle<HeapType> type, | 770 Register object_reg, |
| 859 Register object_reg, | 771 Handle<JSObject> holder, |
| 860 Handle<JSObject> holder, | 772 Handle<Name> name, |
| 861 Handle<Name> name, | 773 Handle<Object> callback) { |
| 862 Handle<Object> callback) { | |
| 863 Label miss; | 774 Label miss; |
| 864 | 775 |
| 865 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 776 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); |
| 866 | 777 |
| 867 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 778 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 868 ASSERT(!reg.is(scratch2())); | 779 ASSERT(!reg.is(scratch2())); |
| 869 ASSERT(!reg.is(scratch3())); | 780 ASSERT(!reg.is(scratch3())); |
| 870 ASSERT(!reg.is(scratch4())); | 781 ASSERT(!reg.is(scratch4())); |
| 871 | 782 |
| 872 // Load the properties dictionary. | 783 // Load the properties dictionary. |
| 873 Register dictionary = scratch4(); | 784 Register dictionary = scratch4(); |
| 874 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 785 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
| 875 | 786 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 892 NameDictionary::kElementsStartIndex * kPointerSize; | 803 NameDictionary::kElementsStartIndex * kPointerSize; |
| 893 const int kValueOffset = kElementsStartOffset + kPointerSize; | 804 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 894 __ movp(scratch2(), | 805 __ movp(scratch2(), |
| 895 Operand(dictionary, index, times_pointer_size, | 806 Operand(dictionary, index, times_pointer_size, |
| 896 kValueOffset - kHeapObjectTag)); | 807 kValueOffset - kHeapObjectTag)); |
| 897 __ Move(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); | 808 __ Move(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); |
| 898 __ cmpp(scratch2(), scratch3()); | 809 __ cmpp(scratch2(), scratch3()); |
| 899 __ j(not_equal, &miss); | 810 __ j(not_equal, &miss); |
| 900 } | 811 } |
| 901 | 812 |
| 902 HandlerFrontendFooter(name, &miss); | 813 FrontendFooter(name, &miss); |
| 903 return reg; | 814 return reg; |
| 904 } | 815 } |
| 905 | 816 |
| 906 | 817 |
| 907 void LoadStubCompiler::GenerateLoadField(Register reg, | 818 void NamedLoadHandlerCompiler::GenerateLoadField( |
| 908 Handle<JSObject> holder, | 819 Register reg, Handle<JSObject> holder, FieldIndex field, |
| 909 FieldIndex field, | 820 Representation representation) { |
| 910 Representation representation) { | |
| 911 if (!reg.is(receiver())) __ movp(receiver(), reg); | 821 if (!reg.is(receiver())) __ movp(receiver(), reg); |
| 912 LoadFieldStub stub(isolate(), field); | 822 LoadFieldStub stub(isolate(), field); |
| 913 GenerateTailCall(masm(), stub.GetCode()); | 823 GenerateTailCall(masm(), stub.GetCode()); |
| 914 } | 824 } |
| 915 | 825 |
| 916 | 826 |
| 917 void LoadStubCompiler::GenerateLoadCallback( | 827 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
| 918 Register reg, | 828 Register reg, Handle<ExecutableAccessorInfo> callback) { |
| 919 Handle<ExecutableAccessorInfo> callback) { | |
| 920 // Insert additional parameters into the stack frame above return address. | 829 // Insert additional parameters into the stack frame above return address. |
| 921 ASSERT(!scratch4().is(reg)); | 830 ASSERT(!scratch4().is(reg)); |
| 922 __ PopReturnAddressTo(scratch4()); | 831 __ PopReturnAddressTo(scratch4()); |
| 923 | 832 |
| 924 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 833 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
| 925 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 834 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
| 926 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 835 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
| 927 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 836 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
| 928 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 837 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
| 929 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 838 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 952 // Abi for CallApiGetter | 861 // Abi for CallApiGetter |
| 953 Register api_function_address = r8; | 862 Register api_function_address = r8; |
| 954 Address getter_address = v8::ToCData<Address>(callback->getter()); | 863 Address getter_address = v8::ToCData<Address>(callback->getter()); |
| 955 __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE); | 864 __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE); |
| 956 | 865 |
| 957 CallApiGetterStub stub(isolate()); | 866 CallApiGetterStub stub(isolate()); |
| 958 __ TailCallStub(&stub); | 867 __ TailCallStub(&stub); |
| 959 } | 868 } |
| 960 | 869 |
| 961 | 870 |
| 962 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 871 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 963 // Return the constant value. | 872 // Return the constant value. |
| 964 __ Move(rax, value); | 873 __ Move(rax, value); |
| 965 __ ret(0); | 874 __ ret(0); |
| 966 } | 875 } |
| 967 | 876 |
| 968 | 877 |
| 969 void LoadStubCompiler::GenerateLoadInterceptor( | 878 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
| 970 Register holder_reg, | 879 Register holder_reg, Handle<Object> object, |
| 971 Handle<Object> object, | 880 Handle<JSObject> interceptor_holder, LookupResult* lookup, |
| 972 Handle<JSObject> interceptor_holder, | |
| 973 LookupResult* lookup, | |
| 974 Handle<Name> name) { | 881 Handle<Name> name) { |
| 975 ASSERT(interceptor_holder->HasNamedInterceptor()); | 882 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 976 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 883 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 977 | 884 |
| 978 // So far the most popular follow ups for interceptor loads are FIELD | 885 // So far the most popular follow ups for interceptor loads are FIELD |
| 979 // and CALLBACKS, so inline only them, other cases may be added | 886 // and CALLBACKS, so inline only them, other cases may be added |
| 980 // later. | 887 // later. |
| 981 bool compile_followup_inline = false; | 888 bool compile_followup_inline = false; |
| 982 if (lookup->IsFound() && lookup->IsCacheable()) { | 889 if (lookup->IsFound() && lookup->IsCacheable()) { |
| 983 if (lookup->IsField()) { | 890 if (lookup->IsField()) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 this->name(), interceptor_holder); | 957 this->name(), interceptor_holder); |
| 1051 __ PushReturnAddressFrom(scratch2()); | 958 __ PushReturnAddressFrom(scratch2()); |
| 1052 | 959 |
| 1053 ExternalReference ref = ExternalReference( | 960 ExternalReference ref = ExternalReference( |
| 1054 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); | 961 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); |
| 1055 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); | 962 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
| 1056 } | 963 } |
| 1057 } | 964 } |
| 1058 | 965 |
| 1059 | 966 |
| 1060 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 967 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 1061 Handle<JSObject> object, | 968 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
| 1062 Handle<JSObject> holder, | |
| 1063 Handle<Name> name, | |
| 1064 Handle<ExecutableAccessorInfo> callback) { | 969 Handle<ExecutableAccessorInfo> callback) { |
| 1065 Register holder_reg = HandlerFrontend( | 970 Register holder_reg = |
| 1066 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | 971 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
| 1067 | 972 |
| 1068 __ PopReturnAddressTo(scratch1()); | 973 __ PopReturnAddressTo(scratch1()); |
| 1069 __ Push(receiver()); | 974 __ Push(receiver()); |
| 1070 __ Push(holder_reg); | 975 __ Push(holder_reg); |
| 1071 __ Push(callback); // callback info | 976 __ Push(callback); // callback info |
| 1072 __ Push(name); | 977 __ Push(name); |
| 1073 __ Push(value()); | 978 __ Push(value()); |
| 1074 __ PushReturnAddressFrom(scratch1()); | 979 __ PushReturnAddressFrom(scratch1()); |
| 1075 | 980 |
| 1076 // Do tail-call to the runtime system. | 981 // Do tail-call to the runtime system. |
| 1077 ExternalReference store_callback_property = | 982 ExternalReference store_callback_property = |
| 1078 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 983 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 1079 __ TailCallExternalReference(store_callback_property, 5, 1); | 984 __ TailCallExternalReference(store_callback_property, 5, 1); |
| 1080 | 985 |
| 1081 // Return the generated code. | 986 // Return the generated code. |
| 1082 return GetCode(kind(), Code::FAST, name); | 987 return GetCode(kind(), Code::FAST, name); |
| 1083 } | 988 } |
| 1084 | 989 |
| 1085 | 990 |
| 1086 #undef __ | 991 #undef __ |
| 1087 #define __ ACCESS_MASM(masm) | 992 #define __ ACCESS_MASM(masm) |
| 1088 | 993 |
| 1089 | 994 |
| 1090 void StoreStubCompiler::GenerateStoreViaSetter( | 995 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
| 1091 MacroAssembler* masm, | 996 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 1092 Handle<HeapType> type, | |
| 1093 Register receiver, | |
| 1094 Handle<JSFunction> setter) { | 997 Handle<JSFunction> setter) { |
| 1095 // ----------- S t a t e ------------- | 998 // ----------- S t a t e ------------- |
| 1096 // -- rsp[0] : return address | 999 // -- rsp[0] : return address |
| 1097 // ----------------------------------- | 1000 // ----------------------------------- |
| 1098 { | 1001 { |
| 1099 FrameScope scope(masm, StackFrame::INTERNAL); | 1002 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1100 | 1003 |
| 1101 // Save value register, so we can restore it later. | 1004 // Save value register, so we can restore it later. |
| 1102 __ Push(value()); | 1005 __ Push(value()); |
| 1103 | 1006 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1127 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1030 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1128 } | 1031 } |
| 1129 __ ret(0); | 1032 __ ret(0); |
| 1130 } | 1033 } |
| 1131 | 1034 |
| 1132 | 1035 |
| 1133 #undef __ | 1036 #undef __ |
| 1134 #define __ ACCESS_MASM(masm()) | 1037 #define __ ACCESS_MASM(masm()) |
| 1135 | 1038 |
| 1136 | 1039 |
| 1137 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 1040 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
| 1138 Handle<JSObject> object, | 1041 Handle<JSObject> object, Handle<Name> name) { |
| 1139 Handle<Name> name) { | |
| 1140 __ PopReturnAddressTo(scratch1()); | 1042 __ PopReturnAddressTo(scratch1()); |
| 1141 __ Push(receiver()); | 1043 __ Push(receiver()); |
| 1142 __ Push(this->name()); | 1044 __ Push(this->name()); |
| 1143 __ Push(value()); | 1045 __ Push(value()); |
| 1144 __ PushReturnAddressFrom(scratch1()); | 1046 __ PushReturnAddressFrom(scratch1()); |
| 1145 | 1047 |
| 1146 // Do tail-call to the runtime system. | 1048 // Do tail-call to the runtime system. |
| 1147 ExternalReference store_ic_property = | 1049 ExternalReference store_ic_property = |
| 1148 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 1050 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 1149 __ TailCallExternalReference(store_ic_property, 3, 1); | 1051 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 1150 | 1052 |
| 1151 // Return the generated code. | 1053 // Return the generated code. |
| 1152 return GetCode(kind(), Code::FAST, name); | 1054 return GetCode(kind(), Code::FAST, name); |
| 1153 } | 1055 } |
| 1154 | 1056 |
| 1155 | 1057 |
| 1156 void StoreStubCompiler::GenerateStoreArrayLength() { | 1058 void NamedStoreHandlerCompiler::GenerateStoreArrayLength() { |
| 1157 // Prepare tail call to StoreIC_ArrayLength. | 1059 // Prepare tail call to StoreIC_ArrayLength. |
| 1158 __ PopReturnAddressTo(scratch1()); | 1060 __ PopReturnAddressTo(scratch1()); |
| 1159 __ Push(receiver()); | 1061 __ Push(receiver()); |
| 1160 __ Push(value()); | 1062 __ Push(value()); |
| 1161 __ PushReturnAddressFrom(scratch1()); | 1063 __ PushReturnAddressFrom(scratch1()); |
| 1162 | 1064 |
| 1163 ExternalReference ref = | 1065 ExternalReference ref = |
| 1164 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), | 1066 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), |
| 1165 masm()->isolate()); | 1067 masm()->isolate()); |
| 1166 __ TailCallExternalReference(ref, 2, 1); | 1068 __ TailCallExternalReference(ref, 2, 1); |
| 1167 } | 1069 } |
| 1168 | 1070 |
| 1169 | 1071 |
| 1170 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 1072 Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( |
| 1171 MapHandleList* receiver_maps, | 1073 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
| 1172 CodeHandleList* handler_stubs, | |
| 1173 MapHandleList* transitioned_maps) { | 1074 MapHandleList* transitioned_maps) { |
| 1174 Label miss; | 1075 Label miss; |
| 1175 __ JumpIfSmi(receiver(), &miss, Label::kNear); | 1076 __ JumpIfSmi(receiver(), &miss, Label::kNear); |
| 1176 | 1077 |
| 1177 __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); | 1078 __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); |
| 1178 int receiver_count = receiver_maps->length(); | 1079 int receiver_count = receiver_maps->length(); |
| 1179 for (int i = 0; i < receiver_count; ++i) { | 1080 for (int i = 0; i < receiver_count; ++i) { |
| 1180 // Check map and tail call if there's a match | 1081 // Check map and tail call if there's a match |
| 1181 __ Cmp(scratch1(), receiver_maps->at(i)); | 1082 __ Cmp(scratch1(), receiver_maps->at(i)); |
| 1182 if (transitioned_maps->at(i).is_null()) { | 1083 if (transitioned_maps->at(i).is_null()) { |
| 1183 __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); | 1084 __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); |
| 1184 } else { | 1085 } else { |
| 1185 Label next_map; | 1086 Label next_map; |
| 1186 __ j(not_equal, &next_map, Label::kNear); | 1087 __ j(not_equal, &next_map, Label::kNear); |
| 1187 __ Move(transition_map(), | 1088 __ Move(transition_map(), |
| 1188 transitioned_maps->at(i), | 1089 transitioned_maps->at(i), |
| 1189 RelocInfo::EMBEDDED_OBJECT); | 1090 RelocInfo::EMBEDDED_OBJECT); |
| 1190 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 1091 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
| 1191 __ bind(&next_map); | 1092 __ bind(&next_map); |
| 1192 } | 1093 } |
| 1193 } | 1094 } |
| 1194 | 1095 |
| 1195 __ bind(&miss); | 1096 __ bind(&miss); |
| 1196 | 1097 |
| 1197 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1098 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1198 | 1099 |
| 1199 // Return the generated code. | 1100 // Return the generated code. |
| 1200 return GetICCode( | 1101 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 1201 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
| 1202 } | 1102 } |
| 1203 | 1103 |
| 1204 | 1104 |
| 1205 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, | 1105 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
| 1206 Handle<JSObject> last, | 1106 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { |
| 1207 Handle<Name> name) { | 1107 NonexistentFrontend(type, last, name); |
| 1208 NonexistentHandlerFrontend(type, last, name); | |
| 1209 | 1108 |
| 1210 // Return undefined if maps of the full prototype chain are still the | 1109 // Return undefined if maps of the full prototype chain are still the |
| 1211 // same and no global property with this name contains a value. | 1110 // same and no global property with this name contains a value. |
| 1212 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1111 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1213 __ ret(0); | 1112 __ ret(0); |
| 1214 | 1113 |
| 1215 // Return the generated code. | 1114 // Return the generated code. |
| 1216 return GetCode(kind(), Code::FAST, name); | 1115 return GetCode(kind(), Code::FAST, name); |
| 1217 } | 1116 } |
| 1218 | 1117 |
| 1219 | 1118 |
| 1220 Register* LoadStubCompiler::registers() { | 1119 Register* PropertyAccessCompiler::load_calling_convention() { |
| 1221 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1120 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
| 1222 Register receiver = LoadIC::ReceiverRegister(); | 1121 Register receiver = LoadIC::ReceiverRegister(); |
| 1223 Register name = LoadIC::NameRegister(); | 1122 Register name = LoadIC::NameRegister(); |
| 1224 static Register registers[] = { receiver, name, rax, rbx, rdi, r8 }; | 1123 static Register registers[] = { receiver, name, rax, rbx, rdi, r8 }; |
| 1225 return registers; | 1124 return registers; |
| 1226 } | 1125 } |
| 1227 | 1126 |
| 1228 | 1127 |
| 1229 Register* KeyedLoadStubCompiler::registers() { | 1128 Register* PropertyAccessCompiler::store_calling_convention() { |
| 1230 // receiver, name, scratch1, scratch2, scratch3, scratch4. | |
| 1231 Register receiver = LoadIC::ReceiverRegister(); | |
| 1232 Register name = LoadIC::NameRegister(); | |
| 1233 static Register registers[] = { receiver, name, rax, rbx, rdi, r8 }; | |
| 1234 return registers; | |
| 1235 } | |
| 1236 | |
| 1237 | |
| 1238 Register StoreStubCompiler::value() { | |
| 1239 return StoreIC::ValueRegister(); | |
| 1240 } | |
| 1241 | |
| 1242 | |
| 1243 Register* StoreStubCompiler::registers() { | |
| 1244 // receiver, name, scratch1, scratch2, scratch3. | 1129 // receiver, name, scratch1, scratch2, scratch3. |
| 1245 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1130 Register receiver = KeyedStoreIC::ReceiverRegister(); |
| 1246 Register name = KeyedStoreIC::NameRegister(); | 1131 Register name = KeyedStoreIC::NameRegister(); |
| 1247 static Register registers[] = { receiver, name, rbx, rdi, r8 }; | 1132 static Register registers[] = { receiver, name, rbx, rdi, r8 }; |
| 1248 return registers; | 1133 return registers; |
| 1249 } | 1134 } |
| 1250 | 1135 |
| 1251 | 1136 |
| 1252 Register* KeyedStoreStubCompiler::registers() { | 1137 Register* PropertyAccessCompiler::keyed_store_calling_convention() { |
| 1253 // receiver, name, scratch1/map, scratch2, scratch3. | 1138 // receiver, name, scratch1/map, scratch2, scratch3. |
| 1254 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1139 Register receiver = KeyedStoreIC::ReceiverRegister(); |
| 1255 Register name = KeyedStoreIC::NameRegister(); | 1140 Register name = KeyedStoreIC::NameRegister(); |
| 1256 Register map = KeyedStoreIC::MapRegister(); | 1141 Register map = KeyedStoreIC::MapRegister(); |
| 1257 static Register registers[] = { receiver, name, map, rdi, r8 }; | 1142 static Register registers[] = { receiver, name, map, rdi, r8 }; |
| 1258 return registers; | 1143 return registers; |
| 1259 } | 1144 } |
| 1260 | 1145 |
| 1261 | 1146 |
| 1147 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1148 |
| 1149 |
| 1262 #undef __ | 1150 #undef __ |
| 1263 #define __ ACCESS_MASM(masm) | 1151 #define __ ACCESS_MASM(masm) |
| 1264 | 1152 |
| 1265 | 1153 |
| 1266 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1154 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
| 1267 Handle<HeapType> type, | 1155 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 1268 Register receiver, | 1156 Handle<JSFunction> getter) { |
| 1269 Handle<JSFunction> getter) { | |
| 1270 // ----------- S t a t e ------------- | 1157 // ----------- S t a t e ------------- |
| 1271 // -- rax : receiver | 1158 // -- rax : receiver |
| 1272 // -- rcx : name | 1159 // -- rcx : name |
| 1273 // -- rsp[0] : return address | 1160 // -- rsp[0] : return address |
| 1274 // ----------------------------------- | 1161 // ----------------------------------- |
| 1275 { | 1162 { |
| 1276 FrameScope scope(masm, StackFrame::INTERNAL); | 1163 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1277 | 1164 |
| 1278 if (!getter.is_null()) { | 1165 if (!getter.is_null()) { |
| 1279 // Call the JavaScript getter with the receiver on the stack. | 1166 // Call the JavaScript getter with the receiver on the stack. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1297 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1184 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1298 } | 1185 } |
| 1299 __ ret(0); | 1186 __ ret(0); |
| 1300 } | 1187 } |
| 1301 | 1188 |
| 1302 | 1189 |
| 1303 #undef __ | 1190 #undef __ |
| 1304 #define __ ACCESS_MASM(masm()) | 1191 #define __ ACCESS_MASM(masm()) |
| 1305 | 1192 |
| 1306 | 1193 |
| 1307 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 1194 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| 1308 Handle<HeapType> type, | 1195 Handle<HeapType> type, Handle<GlobalObject> global, |
| 1309 Handle<GlobalObject> global, | 1196 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
| 1310 Handle<PropertyCell> cell, | |
| 1311 Handle<Name> name, | |
| 1312 bool is_dont_delete) { | |
| 1313 Label miss; | 1197 Label miss; |
| 1314 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since | 1198 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since |
| 1315 // rax is used as receiver(), which we would otherwise clobber before a | 1199 // rax is used as receiver(), which we would otherwise clobber before a |
| 1316 // potential miss. | 1200 // potential miss. |
| 1317 HandlerFrontendHeader(type, receiver(), global, name, &miss); | 1201 FrontendHeader(type, receiver(), global, name, &miss); |
| 1318 | 1202 |
| 1319 // Get the value from the cell. | 1203 // Get the value from the cell. |
| 1320 __ Move(rbx, cell); | 1204 __ Move(rbx, cell); |
| 1321 __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); | 1205 __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); |
| 1322 | 1206 |
| 1323 // Check for deleted property if property can actually be deleted. | 1207 // Check for deleted property if property can actually be deleted. |
| 1324 if (!is_dont_delete) { | 1208 if (!is_dont_delete) { |
| 1325 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 1209 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 1326 __ j(equal, &miss); | 1210 __ j(equal, &miss); |
| 1327 } else if (FLAG_debug_code) { | 1211 } else if (FLAG_debug_code) { |
| 1328 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 1212 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 1329 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); | 1213 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); |
| 1330 } | 1214 } |
| 1331 | 1215 |
| 1332 Counters* counters = isolate()->counters(); | 1216 Counters* counters = isolate()->counters(); |
| 1333 __ IncrementCounter(counters->named_load_global_stub(), 1); | 1217 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 1334 __ movp(rax, rbx); | 1218 __ movp(rax, rbx); |
| 1335 __ ret(0); | 1219 __ ret(0); |
| 1336 | 1220 |
| 1337 HandlerFrontendFooter(name, &miss); | 1221 FrontendFooter(name, &miss); |
| 1338 | 1222 |
| 1339 // Return the generated code. | 1223 // Return the generated code. |
| 1340 return GetCode(kind(), Code::NORMAL, name); | 1224 return GetCode(kind(), Code::NORMAL, name); |
| 1341 } | 1225 } |
| 1342 | 1226 |
| 1343 | 1227 |
| 1344 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 1228 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
| 1345 TypeHandleList* types, | 1229 CodeHandleList* handlers, |
| 1346 CodeHandleList* handlers, | 1230 Handle<Name> name, |
| 1347 Handle<Name> name, | 1231 Code::StubType type, |
| 1348 Code::StubType type, | 1232 IcCheckType check) { |
| 1349 IcCheckType check) { | |
| 1350 Label miss; | 1233 Label miss; |
| 1351 | 1234 |
| 1352 if (check == PROPERTY && | 1235 if (check == PROPERTY && |
| 1353 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | 1236 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { |
| 1354 __ Cmp(this->name(), name); | 1237 __ Cmp(this->name(), name); |
| 1355 __ j(not_equal, &miss); | 1238 __ j(not_equal, &miss); |
| 1356 } | 1239 } |
| 1357 | 1240 |
| 1358 Label number_case; | 1241 Label number_case; |
| 1359 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1242 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1381 } | 1264 } |
| 1382 } | 1265 } |
| 1383 ASSERT(number_of_handled_maps > 0); | 1266 ASSERT(number_of_handled_maps > 0); |
| 1384 | 1267 |
| 1385 __ bind(&miss); | 1268 __ bind(&miss); |
| 1386 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1269 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1387 | 1270 |
| 1388 // Return the generated code. | 1271 // Return the generated code. |
| 1389 InlineCacheState state = | 1272 InlineCacheState state = |
| 1390 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 1273 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
| 1391 return GetICCode(kind(), type, name, state); | 1274 return GetCode(kind(), type, name, state); |
| 1392 } | 1275 } |
| 1393 | 1276 |
| 1394 | 1277 |
| 1395 #undef __ | 1278 #undef __ |
| 1396 #define __ ACCESS_MASM(masm) | 1279 #define __ ACCESS_MASM(masm) |
| 1397 | 1280 |
| 1398 | 1281 |
| 1399 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( | 1282 void IndexedHandlerCompiler::GenerateLoadDictionaryElement( |
| 1400 MacroAssembler* masm) { | 1283 MacroAssembler* masm) { |
| 1401 // ----------- S t a t e ------------- | 1284 // ----------- S t a t e ------------- |
| 1402 // -- rcx : key | 1285 // -- rcx : key |
| 1403 // -- rdx : receiver | 1286 // -- rdx : receiver |
| 1404 // -- rsp[0] : return address | 1287 // -- rsp[0] : return address |
| 1405 // ----------------------------------- | 1288 // ----------------------------------- |
| 1406 ASSERT(rdx.is(LoadIC::ReceiverRegister())); | 1289 ASSERT(rdx.is(LoadIC::ReceiverRegister())); |
| 1407 ASSERT(rcx.is(LoadIC::NameRegister())); | 1290 ASSERT(rcx.is(LoadIC::NameRegister())); |
| 1408 Label slow, miss; | 1291 Label slow, miss; |
| 1409 | 1292 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1438 // ----------------------------------- | 1321 // ----------------------------------- |
| 1439 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1322 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1440 } | 1323 } |
| 1441 | 1324 |
| 1442 | 1325 |
| 1443 #undef __ | 1326 #undef __ |
| 1444 | 1327 |
| 1445 } } // namespace v8::internal | 1328 } } // namespace v8::internal |
| 1446 | 1329 |
| 1447 #endif // V8_TARGET_ARCH_X64 | 1330 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |