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 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 328 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
329 __ Move( | 329 __ Move( |
330 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); | 330 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); |
331 | 331 |
332 // Jump to stub. | 332 // Jump to stub. |
333 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 333 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
334 __ TailCallStub(&stub); | 334 __ TailCallStub(&stub); |
335 } | 335 } |
336 | 336 |
337 | 337 |
338 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, | |
339 Label* label, | |
340 Handle<Name> name) { | |
341 if (!label->is_unused()) { | |
342 __ bind(label); | |
343 __ Move(this->name(), name); | |
344 } | |
345 } | |
346 | |
347 | |
348 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 338 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
349 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 339 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
350 Register scratch, Label* miss) { | 340 Register scratch, Label* miss) { |
351 Handle<PropertyCell> cell = | 341 Handle<PropertyCell> cell = |
352 JSGlobalObject::EnsurePropertyCell(global, name); | 342 JSGlobalObject::EnsurePropertyCell(global, name); |
353 ASSERT(cell->value()->IsTheHole()); | 343 ASSERT(cell->value()->IsTheHole()); |
354 __ Move(scratch, cell); | 344 __ Move(scratch, cell); |
355 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), | 345 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), |
356 masm->isolate()->factory()->the_hole_value()); | 346 masm->isolate()->factory()->the_hole_value()); |
357 __ j(not_equal, miss); | 347 __ j(not_equal, miss); |
358 } | 348 } |
359 | 349 |
360 | 350 |
| 351 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
| 352 Handle<Code> code) { |
| 353 __ jmp(code, RelocInfo::CODE_TARGET); |
| 354 } |
| 355 |
| 356 |
| 357 #undef __ |
| 358 #define __ ACCESS_MASM((masm())) |
| 359 |
| 360 |
| 361 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, |
| 362 Handle<Name> name) { |
| 363 if (!label->is_unused()) { |
| 364 __ bind(label); |
| 365 __ Move(this->name(), name); |
| 366 } |
| 367 } |
| 368 |
| 369 |
361 void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( | 370 void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( |
362 MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg, | 371 Register holder_reg, Handle<Name> name, Label* miss) { |
363 Handle<Name> name, Label* miss) { | 372 if (holder()->IsJSGlobalObject()) { |
364 if (holder->IsJSGlobalObject()) { | 373 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(holder()), |
365 GenerateCheckPropertyCell( | 374 name, scratch1(), miss); |
366 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); | 375 } else if (!holder()->HasFastProperties()) { |
367 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 376 GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1(), |
368 GenerateDictionaryNegativeLookup( | 377 scratch2()); |
369 masm, miss, holder_reg, name, scratch1(), scratch2()); | |
370 } | 378 } |
371 } | 379 } |
372 | 380 |
373 | 381 |
374 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 382 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
375 // store is successful. | 383 // store is successful. |
376 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 384 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
377 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, | 385 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
378 Handle<Name> name, Register receiver_reg, Register storage_reg, | 386 Register storage_reg, Register value_reg, Register scratch1, |
379 Register value_reg, Register scratch1, Register scratch2, Register unused, | 387 Register scratch2, Register unused, Label* miss_label, Label* slow) { |
380 Label* miss_label, Label* slow) { | |
381 int descriptor = transition->LastAdded(); | 388 int descriptor = transition->LastAdded(); |
382 DescriptorArray* descriptors = transition->instance_descriptors(); | 389 DescriptorArray* descriptors = transition->instance_descriptors(); |
383 PropertyDetails details = descriptors->GetDetails(descriptor); | 390 PropertyDetails details = descriptors->GetDetails(descriptor); |
384 Representation representation = details.representation(); | 391 Representation representation = details.representation(); |
385 ASSERT(!representation.IsNone()); | 392 ASSERT(!representation.IsNone()); |
386 | 393 |
387 if (details.type() == CONSTANT) { | 394 if (details.type() == CONSTANT) { |
388 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 395 Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); |
389 __ Cmp(value_reg, constant); | 396 __ Cmp(value_reg, constant); |
390 __ j(not_equal, miss_label); | 397 __ j(not_equal, miss_label); |
391 } else if (representation.IsSmi()) { | 398 } else if (representation.IsSmi()) { |
392 __ JumpIfNotSmi(value_reg, miss_label); | 399 __ JumpIfNotSmi(value_reg, miss_label); |
393 } else if (representation.IsHeapObject()) { | 400 } else if (representation.IsHeapObject()) { |
394 __ JumpIfSmi(value_reg, miss_label); | 401 __ JumpIfSmi(value_reg, miss_label); |
395 HeapType* field_type = descriptors->GetFieldType(descriptor); | 402 HeapType* field_type = descriptors->GetFieldType(descriptor); |
396 HeapType::Iterator<Map> it = field_type->Classes(); | 403 HeapType::Iterator<Map> it = field_type->Classes(); |
397 if (!it.Done()) { | 404 if (!it.Done()) { |
398 Label do_store; | 405 Label do_store; |
(...skipping 11 matching lines...) Expand all Loading... |
410 } else if (representation.IsDouble()) { | 417 } else if (representation.IsDouble()) { |
411 Label do_store, heap_number; | 418 Label do_store, heap_number; |
412 __ AllocateHeapNumber(storage_reg, scratch1, slow, MUTABLE); | 419 __ AllocateHeapNumber(storage_reg, scratch1, slow, MUTABLE); |
413 | 420 |
414 __ JumpIfNotSmi(value_reg, &heap_number); | 421 __ JumpIfNotSmi(value_reg, &heap_number); |
415 __ SmiToInteger32(scratch1, value_reg); | 422 __ SmiToInteger32(scratch1, value_reg); |
416 __ Cvtlsi2sd(xmm0, scratch1); | 423 __ Cvtlsi2sd(xmm0, scratch1); |
417 __ jmp(&do_store); | 424 __ jmp(&do_store); |
418 | 425 |
419 __ bind(&heap_number); | 426 __ bind(&heap_number); |
420 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 427 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, |
421 miss_label, DONT_DO_SMI_CHECK); | 428 DONT_DO_SMI_CHECK); |
422 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 429 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
423 | 430 |
424 __ bind(&do_store); | 431 __ bind(&do_store); |
425 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 432 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |
426 } | 433 } |
427 | 434 |
428 // Stub never generated for objects that require access checks. | 435 // Stub never generated for objects that require access checks. |
429 ASSERT(!transition->is_access_check_needed()); | 436 ASSERT(!transition->is_access_check_needed()); |
430 | 437 |
431 // Perform map transition for the receiver if necessary. | 438 // Perform map transition for the receiver if necessary. |
432 if (details.type() == FIELD && | 439 if (details.type() == FIELD && |
433 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 440 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
434 // The properties must be extended before we can store the value. | 441 // The properties must be extended before we can store the value. |
435 // We jump to a runtime call that extends the properties array. | 442 // We jump to a runtime call that extends the properties array. |
436 __ PopReturnAddressTo(scratch1); | 443 __ PopReturnAddressTo(scratch1); |
437 __ Push(receiver_reg); | 444 __ Push(receiver_reg); |
438 __ Push(transition); | 445 __ Push(transition); |
439 __ Push(value_reg); | 446 __ Push(value_reg); |
440 __ PushReturnAddressFrom(scratch1); | 447 __ PushReturnAddressFrom(scratch1); |
441 __ TailCallExternalReference( | 448 __ TailCallExternalReference( |
442 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 449 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
443 masm->isolate()), | 450 isolate()), |
444 3, | 451 3, 1); |
445 1); | |
446 return; | 452 return; |
447 } | 453 } |
448 | 454 |
449 // Update the map of the object. | 455 // Update the map of the object. |
450 __ Move(scratch1, transition); | 456 __ Move(scratch1, transition); |
451 __ movp(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); | 457 __ movp(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); |
452 | 458 |
453 // Update the write barrier for the map field. | 459 // Update the write barrier for the map field. |
454 __ RecordWriteField(receiver_reg, | 460 __ RecordWriteField(receiver_reg, |
455 HeapObject::kMapOffset, | 461 HeapObject::kMapOffset, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 | 524 |
519 // Return the value (register rax). | 525 // Return the value (register rax). |
520 ASSERT(value_reg.is(rax)); | 526 ASSERT(value_reg.is(rax)); |
521 __ ret(0); | 527 __ ret(0); |
522 } | 528 } |
523 | 529 |
524 | 530 |
525 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 531 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
526 // but may be destroyed if store is successful. | 532 // but may be destroyed if store is successful. |
527 void NamedStoreHandlerCompiler::GenerateStoreField( | 533 void NamedStoreHandlerCompiler::GenerateStoreField( |
528 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 534 Handle<JSObject> object, LookupResult* lookup, Register receiver_reg, |
529 Register receiver_reg, Register name_reg, Register value_reg, | 535 Register name_reg, Register value_reg, Register scratch1, Register scratch2, |
530 Register scratch1, Register scratch2, Label* miss_label) { | 536 Label* miss_label) { |
531 // Stub never generated for non-global objects that require access | 537 // Stub never generated for objects that require access checks. |
532 // checks. | 538 ASSERT(!object->IsAccessCheckNeeded()); |
533 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 539 ASSERT(!object->IsJSGlobalProxy()); |
534 | 540 |
535 FieldIndex index = lookup->GetFieldIndex(); | 541 FieldIndex index = lookup->GetFieldIndex(); |
536 | 542 |
537 Representation representation = lookup->representation(); | 543 Representation representation = lookup->representation(); |
538 ASSERT(!representation.IsNone()); | 544 ASSERT(!representation.IsNone()); |
539 if (representation.IsSmi()) { | 545 if (representation.IsSmi()) { |
540 __ JumpIfNotSmi(value_reg, miss_label); | 546 __ JumpIfNotSmi(value_reg, miss_label); |
541 } else if (representation.IsHeapObject()) { | 547 } else if (representation.IsHeapObject()) { |
542 __ JumpIfSmi(value_reg, miss_label); | 548 __ JumpIfSmi(value_reg, miss_label); |
543 HeapType* field_type = lookup->GetFieldType(); | 549 HeapType* field_type = lookup->GetFieldType(); |
(...skipping 22 matching lines...) Expand all Loading... |
566 } | 572 } |
567 | 573 |
568 // Store the value into the storage. | 574 // Store the value into the storage. |
569 Label do_store, heap_number; | 575 Label do_store, heap_number; |
570 __ JumpIfNotSmi(value_reg, &heap_number); | 576 __ JumpIfNotSmi(value_reg, &heap_number); |
571 __ SmiToInteger32(scratch2, value_reg); | 577 __ SmiToInteger32(scratch2, value_reg); |
572 __ Cvtlsi2sd(xmm0, scratch2); | 578 __ Cvtlsi2sd(xmm0, scratch2); |
573 __ jmp(&do_store); | 579 __ jmp(&do_store); |
574 | 580 |
575 __ bind(&heap_number); | 581 __ bind(&heap_number); |
576 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 582 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, |
577 miss_label, DONT_DO_SMI_CHECK); | 583 DONT_DO_SMI_CHECK); |
578 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 584 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
579 __ bind(&do_store); | 585 __ bind(&do_store); |
580 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); | 586 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); |
581 // Return the value (register rax). | 587 // Return the value (register rax). |
582 ASSERT(value_reg.is(rax)); | 588 ASSERT(value_reg.is(rax)); |
583 __ ret(0); | 589 __ ret(0); |
584 return; | 590 return; |
585 } | 591 } |
586 | 592 |
587 // TODO(verwaest): Share this code as a code stub. | 593 // TODO(verwaest): Share this code as a code stub. |
(...skipping 26 matching lines...) Expand all Loading... |
614 EMIT_REMEMBERED_SET, smi_check); | 620 EMIT_REMEMBERED_SET, smi_check); |
615 } | 621 } |
616 } | 622 } |
617 | 623 |
618 // Return the value (register rax). | 624 // Return the value (register rax). |
619 ASSERT(value_reg.is(rax)); | 625 ASSERT(value_reg.is(rax)); |
620 __ ret(0); | 626 __ ret(0); |
621 } | 627 } |
622 | 628 |
623 | 629 |
624 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, | |
625 Handle<Code> code) { | |
626 __ jmp(code, RelocInfo::CODE_TARGET); | |
627 } | |
628 | |
629 | |
630 #undef __ | |
631 #define __ ACCESS_MASM((masm())) | |
632 | |
633 | |
634 Register PropertyHandlerCompiler::CheckPrototypes( | 630 Register PropertyHandlerCompiler::CheckPrototypes( |
635 Register object_reg, Register holder_reg, Register scratch1, | 631 Register object_reg, Register holder_reg, Register scratch1, |
636 Register scratch2, Handle<Name> name, Label* miss, | 632 Register scratch2, Handle<Name> name, Label* miss, |
637 PrototypeCheckType check) { | 633 PrototypeCheckType check) { |
638 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 634 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
639 | 635 |
640 // Make sure there's no overlap between holder and object registers. | 636 // Make sure there's no overlap between holder and object registers. |
641 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 637 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
642 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 638 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
643 && !scratch2.is(scratch1)); | 639 && !scratch2.is(scratch1)); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 TailCallBuiltin(masm(), MissBuiltin(kind())); | 746 TailCallBuiltin(masm(), MissBuiltin(kind())); |
751 __ bind(&success); | 747 __ bind(&success); |
752 } | 748 } |
753 } | 749 } |
754 | 750 |
755 | 751 |
756 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 752 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
757 if (!miss->is_unused()) { | 753 if (!miss->is_unused()) { |
758 Label success; | 754 Label success; |
759 __ jmp(&success); | 755 __ jmp(&success); |
760 GenerateRestoreName(masm(), miss, name); | 756 GenerateRestoreName(miss, name); |
761 TailCallBuiltin(masm(), MissBuiltin(kind())); | 757 TailCallBuiltin(masm(), MissBuiltin(kind())); |
762 __ bind(&success); | 758 __ bind(&success); |
763 } | 759 } |
764 } | 760 } |
765 | 761 |
766 | 762 |
767 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 763 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
768 Handle<Name> name, | 764 Handle<Name> name, |
769 Handle<Object> callback) { | 765 Handle<Object> callback) { |
770 Label miss; | 766 Label miss; |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1045 // Do tail-call to the runtime system. | 1041 // Do tail-call to the runtime system. |
1046 ExternalReference store_ic_property = ExternalReference( | 1042 ExternalReference store_ic_property = ExternalReference( |
1047 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1043 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1048 __ TailCallExternalReference(store_ic_property, 3, 1); | 1044 __ TailCallExternalReference(store_ic_property, 3, 1); |
1049 | 1045 |
1050 // Return the generated code. | 1046 // Return the generated code. |
1051 return GetCode(kind(), Code::FAST, name); | 1047 return GetCode(kind(), Code::FAST, name); |
1052 } | 1048 } |
1053 | 1049 |
1054 | 1050 |
1055 void NamedStoreHandlerCompiler::GenerateStoreArrayLength() { | |
1056 // Prepare tail call to StoreIC_ArrayLength. | |
1057 __ PopReturnAddressTo(scratch1()); | |
1058 __ Push(receiver()); | |
1059 __ Push(value()); | |
1060 __ PushReturnAddressFrom(scratch1()); | |
1061 | |
1062 ExternalReference ref = | |
1063 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), | |
1064 masm()->isolate()); | |
1065 __ TailCallExternalReference(ref, 2, 1); | |
1066 } | |
1067 | |
1068 | |
1069 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( | 1051 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( |
1070 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, | 1052 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
1071 MapHandleList* transitioned_maps) { | 1053 MapHandleList* transitioned_maps) { |
1072 Label miss; | 1054 Label miss; |
1073 __ JumpIfSmi(receiver(), &miss, Label::kNear); | 1055 __ JumpIfSmi(receiver(), &miss, Label::kNear); |
1074 | 1056 |
1075 __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); | 1057 __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); |
1076 int receiver_count = receiver_maps->length(); | 1058 int receiver_count = receiver_maps->length(); |
1077 for (int i = 0; i < receiver_count; ++i) { | 1059 for (int i = 0; i < receiver_count; ++i) { |
1078 // Check map and tail call if there's a match | 1060 // Check map and tail call if there's a match |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1320 // ----------------------------------- | 1302 // ----------------------------------- |
1321 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1303 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1322 } | 1304 } |
1323 | 1305 |
1324 | 1306 |
1325 #undef __ | 1307 #undef __ |
1326 | 1308 |
1327 } } // namespace v8::internal | 1309 } } // namespace v8::internal |
1328 | 1310 |
1329 #endif // V8_TARGET_ARCH_X64 | 1311 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |