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 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 // Put api_function_address in place. | 363 // Put api_function_address in place. |
364 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 364 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
365 __ mov(api_function_address, Immediate(function_address)); | 365 __ mov(api_function_address, Immediate(function_address)); |
366 | 366 |
367 // Jump to stub. | 367 // Jump to stub. |
368 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 368 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
369 __ TailCallStub(&stub); | 369 __ TailCallStub(&stub); |
370 } | 370 } |
371 | 371 |
372 | 372 |
373 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, | |
374 Label* label, | |
375 Handle<Name> name) { | |
376 if (!label->is_unused()) { | |
377 __ bind(label); | |
378 __ mov(this->name(), Immediate(name)); | |
379 } | |
380 } | |
381 | |
382 | |
383 // Generate code to check that a global property cell is empty. Create | 373 // Generate code to check that a global property cell is empty. Create |
384 // the property cell at compilation time if no cell exists for the | 374 // the property cell at compilation time if no cell exists for the |
385 // property. | 375 // property. |
386 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 376 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
387 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 377 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
388 Register scratch, Label* miss) { | 378 Register scratch, Label* miss) { |
389 Handle<PropertyCell> cell = | 379 Handle<PropertyCell> cell = |
390 JSGlobalObject::EnsurePropertyCell(global, name); | 380 JSGlobalObject::EnsurePropertyCell(global, name); |
391 DCHECK(cell->value()->IsTheHole()); | 381 DCHECK(cell->value()->IsTheHole()); |
392 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); | 382 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); |
393 if (masm->serializer_enabled()) { | 383 if (masm->serializer_enabled()) { |
394 __ mov(scratch, Immediate(cell)); | 384 __ mov(scratch, Immediate(cell)); |
395 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 385 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |
396 Immediate(the_hole)); | 386 Immediate(the_hole)); |
397 } else { | 387 } else { |
398 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); | 388 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); |
399 } | 389 } |
400 __ j(not_equal, miss); | 390 __ j(not_equal, miss); |
401 } | 391 } |
402 | 392 |
403 | 393 |
| 394 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
| 395 Handle<Code> code) { |
| 396 __ jmp(code, RelocInfo::CODE_TARGET); |
| 397 } |
| 398 |
| 399 |
| 400 #undef __ |
| 401 #define __ ACCESS_MASM(masm()) |
| 402 |
| 403 |
| 404 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, |
| 405 Handle<Name> name) { |
| 406 if (!label->is_unused()) { |
| 407 __ bind(label); |
| 408 __ mov(this->name(), Immediate(name)); |
| 409 } |
| 410 } |
| 411 |
| 412 |
404 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 413 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
405 // store is successful. | 414 // store is successful. |
406 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 415 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
407 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, | 416 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
408 Handle<Name> name, Register receiver_reg, Register storage_reg, | 417 Register storage_reg, Register value_reg, Register scratch1, |
409 Register value_reg, Register scratch1, Register scratch2, Register unused, | 418 Register scratch2, Register unused, Label* miss_label, Label* slow) { |
410 Label* miss_label, Label* slow) { | |
411 int descriptor = transition->LastAdded(); | 419 int descriptor = transition->LastAdded(); |
412 DescriptorArray* descriptors = transition->instance_descriptors(); | 420 DescriptorArray* descriptors = transition->instance_descriptors(); |
413 PropertyDetails details = descriptors->GetDetails(descriptor); | 421 PropertyDetails details = descriptors->GetDetails(descriptor); |
414 Representation representation = details.representation(); | 422 Representation representation = details.representation(); |
415 DCHECK(!representation.IsNone()); | 423 DCHECK(!representation.IsNone()); |
416 | 424 |
417 if (details.type() == CONSTANT) { | 425 if (details.type() == CONSTANT) { |
418 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 426 Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); |
419 __ CmpObject(value_reg, constant); | 427 __ CmpObject(value_reg, constant); |
420 __ j(not_equal, miss_label); | 428 __ j(not_equal, miss_label); |
421 } else if (representation.IsSmi()) { | 429 } else if (representation.IsSmi()) { |
422 __ JumpIfNotSmi(value_reg, miss_label); | 430 __ JumpIfNotSmi(value_reg, miss_label); |
423 } else if (representation.IsHeapObject()) { | 431 } else if (representation.IsHeapObject()) { |
424 __ JumpIfSmi(value_reg, miss_label); | 432 __ JumpIfSmi(value_reg, miss_label); |
425 HeapType* field_type = descriptors->GetFieldType(descriptor); | 433 HeapType* field_type = descriptors->GetFieldType(descriptor); |
426 HeapType::Iterator<Map> it = field_type->Classes(); | 434 HeapType::Iterator<Map> it = field_type->Classes(); |
427 if (!it.Done()) { | 435 if (!it.Done()) { |
428 Label do_store; | 436 Label do_store; |
(...skipping 14 matching lines...) Expand all Loading... |
443 | 451 |
444 __ JumpIfNotSmi(value_reg, &heap_number); | 452 __ JumpIfNotSmi(value_reg, &heap_number); |
445 __ SmiUntag(value_reg); | 453 __ SmiUntag(value_reg); |
446 __ push(value_reg); | 454 __ push(value_reg); |
447 __ fild_s(Operand(esp, 0)); | 455 __ fild_s(Operand(esp, 0)); |
448 __ pop(value_reg); | 456 __ pop(value_reg); |
449 __ SmiTag(value_reg); | 457 __ SmiTag(value_reg); |
450 __ jmp(&do_store); | 458 __ jmp(&do_store); |
451 | 459 |
452 __ bind(&heap_number); | 460 __ bind(&heap_number); |
453 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 461 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, |
454 miss_label, DONT_DO_SMI_CHECK); | 462 DONT_DO_SMI_CHECK); |
455 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 463 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); |
456 | 464 |
457 __ bind(&do_store); | 465 __ bind(&do_store); |
458 __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); | 466 __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); |
459 } | 467 } |
460 | 468 |
461 // Stub never generated for objects that require access checks. | 469 // Stub never generated for objects that require access checks. |
462 DCHECK(!transition->is_access_check_needed()); | 470 DCHECK(!transition->is_access_check_needed()); |
463 | 471 |
464 // Perform map transition for the receiver if necessary. | 472 // Perform map transition for the receiver if necessary. |
465 if (details.type() == FIELD && | 473 if (details.type() == FIELD && |
466 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 474 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
467 // The properties must be extended before we can store the value. | 475 // The properties must be extended before we can store the value. |
468 // We jump to a runtime call that extends the properties array. | 476 // We jump to a runtime call that extends the properties array. |
469 __ pop(scratch1); // Return address. | 477 __ pop(scratch1); // Return address. |
470 __ push(receiver_reg); | 478 __ push(receiver_reg); |
471 __ push(Immediate(transition)); | 479 __ push(Immediate(transition)); |
472 __ push(value_reg); | 480 __ push(value_reg); |
473 __ push(scratch1); | 481 __ push(scratch1); |
474 __ TailCallExternalReference( | 482 __ TailCallExternalReference( |
475 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 483 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
476 masm->isolate()), | 484 isolate()), |
477 3, | 485 3, 1); |
478 1); | |
479 return; | 486 return; |
480 } | 487 } |
481 | 488 |
482 // Update the map of the object. | 489 // Update the map of the object. |
483 __ mov(scratch1, Immediate(transition)); | 490 __ mov(scratch1, Immediate(transition)); |
484 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); | 491 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); |
485 | 492 |
486 // Update the write barrier for the map field. | 493 // Update the write barrier for the map field. |
487 __ RecordWriteField(receiver_reg, | 494 __ RecordWriteField(receiver_reg, |
488 HeapObject::kMapOffset, | 495 HeapObject::kMapOffset, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 | 563 |
557 // Return the value (register eax). | 564 // Return the value (register eax). |
558 DCHECK(value_reg.is(eax)); | 565 DCHECK(value_reg.is(eax)); |
559 __ ret(0); | 566 __ ret(0); |
560 } | 567 } |
561 | 568 |
562 | 569 |
563 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 570 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
564 // but may be destroyed if store is successful. | 571 // but may be destroyed if store is successful. |
565 void NamedStoreHandlerCompiler::GenerateStoreField( | 572 void NamedStoreHandlerCompiler::GenerateStoreField( |
566 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 573 Handle<JSObject> object, LookupResult* lookup, Register receiver_reg, |
567 Register receiver_reg, Register name_reg, Register value_reg, | 574 Register name_reg, Register value_reg, Register scratch1, Register scratch2, |
568 Register scratch1, Register scratch2, Label* miss_label) { | 575 Label* miss_label) { |
569 // Stub never generated for non-global objects that require access | 576 // Stub never generated for objects that require access checks. |
570 // checks. | 577 DCHECK(!object->IsAccessCheckNeeded()); |
571 DCHECK(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 578 DCHECK(!object->IsJSGlobalProxy()); |
572 | 579 |
573 FieldIndex index = lookup->GetFieldIndex(); | 580 FieldIndex index = lookup->GetFieldIndex(); |
574 | 581 |
575 Representation representation = lookup->representation(); | 582 Representation representation = lookup->representation(); |
576 DCHECK(!representation.IsNone()); | 583 DCHECK(!representation.IsNone()); |
577 if (representation.IsSmi()) { | 584 if (representation.IsSmi()) { |
578 __ JumpIfNotSmi(value_reg, miss_label); | 585 __ JumpIfNotSmi(value_reg, miss_label); |
579 } else if (representation.IsHeapObject()) { | 586 } else if (representation.IsHeapObject()) { |
580 __ JumpIfSmi(value_reg, miss_label); | 587 __ JumpIfSmi(value_reg, miss_label); |
581 HeapType* field_type = lookup->GetFieldType(); | 588 HeapType* field_type = lookup->GetFieldType(); |
(...skipping 23 matching lines...) Expand all Loading... |
605 // Store the value into the storage. | 612 // Store the value into the storage. |
606 Label do_store, heap_number; | 613 Label do_store, heap_number; |
607 __ JumpIfNotSmi(value_reg, &heap_number); | 614 __ JumpIfNotSmi(value_reg, &heap_number); |
608 __ SmiUntag(value_reg); | 615 __ SmiUntag(value_reg); |
609 __ push(value_reg); | 616 __ push(value_reg); |
610 __ fild_s(Operand(esp, 0)); | 617 __ fild_s(Operand(esp, 0)); |
611 __ pop(value_reg); | 618 __ pop(value_reg); |
612 __ SmiTag(value_reg); | 619 __ SmiTag(value_reg); |
613 __ jmp(&do_store); | 620 __ jmp(&do_store); |
614 __ bind(&heap_number); | 621 __ bind(&heap_number); |
615 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 622 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, |
616 miss_label, DONT_DO_SMI_CHECK); | 623 DONT_DO_SMI_CHECK); |
617 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 624 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); |
618 __ bind(&do_store); | 625 __ bind(&do_store); |
619 __ fstp_d(FieldOperand(scratch1, HeapNumber::kValueOffset)); | 626 __ fstp_d(FieldOperand(scratch1, HeapNumber::kValueOffset)); |
620 // Return the value (register eax). | 627 // Return the value (register eax). |
621 DCHECK(value_reg.is(eax)); | 628 DCHECK(value_reg.is(eax)); |
622 __ ret(0); | 629 __ ret(0); |
623 return; | 630 return; |
624 } | 631 } |
625 | 632 |
626 DCHECK(!representation.IsDouble()); | 633 DCHECK(!representation.IsDouble()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 smi_check); | 667 smi_check); |
661 } | 668 } |
662 } | 669 } |
663 | 670 |
664 // Return the value (register eax). | 671 // Return the value (register eax). |
665 DCHECK(value_reg.is(eax)); | 672 DCHECK(value_reg.is(eax)); |
666 __ ret(0); | 673 __ ret(0); |
667 } | 674 } |
668 | 675 |
669 | 676 |
670 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, | |
671 Handle<Code> code) { | |
672 __ jmp(code, RelocInfo::CODE_TARGET); | |
673 } | |
674 | |
675 | |
676 #undef __ | |
677 #define __ ACCESS_MASM(masm()) | |
678 | |
679 | |
680 Register PropertyHandlerCompiler::CheckPrototypes( | 677 Register PropertyHandlerCompiler::CheckPrototypes( |
681 Register object_reg, Register holder_reg, Register scratch1, | 678 Register object_reg, Register holder_reg, Register scratch1, |
682 Register scratch2, Handle<Name> name, Label* miss, | 679 Register scratch2, Handle<Name> name, Label* miss, |
683 PrototypeCheckType check) { | 680 PrototypeCheckType check) { |
684 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 681 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
685 | 682 |
686 // Make sure there's no overlap between holder and object registers. | 683 // Make sure there's no overlap between holder and object registers. |
687 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 684 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
688 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 685 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
689 && !scratch2.is(scratch1)); | 686 && !scratch2.is(scratch1)); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 TailCallBuiltin(masm(), MissBuiltin(kind())); | 792 TailCallBuiltin(masm(), MissBuiltin(kind())); |
796 __ bind(&success); | 793 __ bind(&success); |
797 } | 794 } |
798 } | 795 } |
799 | 796 |
800 | 797 |
801 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 798 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
802 if (!miss->is_unused()) { | 799 if (!miss->is_unused()) { |
803 Label success; | 800 Label success; |
804 __ jmp(&success); | 801 __ jmp(&success); |
805 GenerateRestoreName(masm(), miss, name); | 802 GenerateRestoreName(miss, name); |
806 TailCallBuiltin(masm(), MissBuiltin(kind())); | 803 TailCallBuiltin(masm(), MissBuiltin(kind())); |
807 __ bind(&success); | 804 __ bind(&success); |
808 } | 805 } |
809 } | 806 } |
810 | 807 |
811 | 808 |
812 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 809 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
813 Handle<Name> name, | 810 Handle<Name> name, |
814 Handle<Object> callback) { | 811 Handle<Object> callback) { |
815 Label miss; | 812 Label miss; |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 // Do tail-call to the runtime system. | 1105 // Do tail-call to the runtime system. |
1109 ExternalReference store_ic_property = ExternalReference( | 1106 ExternalReference store_ic_property = ExternalReference( |
1110 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1107 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1111 __ TailCallExternalReference(store_ic_property, 3, 1); | 1108 __ TailCallExternalReference(store_ic_property, 3, 1); |
1112 | 1109 |
1113 // Return the generated code. | 1110 // Return the generated code. |
1114 return GetCode(kind(), Code::FAST, name); | 1111 return GetCode(kind(), Code::FAST, name); |
1115 } | 1112 } |
1116 | 1113 |
1117 | 1114 |
1118 void NamedStoreHandlerCompiler::GenerateStoreArrayLength() { | |
1119 // Prepare tail call to StoreIC_ArrayLength. | |
1120 __ pop(scratch1()); // remove the return address | |
1121 __ push(receiver()); | |
1122 __ push(value()); | |
1123 __ push(scratch1()); // restore return address | |
1124 | |
1125 ExternalReference ref = | |
1126 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), | |
1127 masm()->isolate()); | |
1128 __ TailCallExternalReference(ref, 2, 1); | |
1129 } | |
1130 | |
1131 | |
1132 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( | 1115 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( |
1133 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, | 1116 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
1134 MapHandleList* transitioned_maps) { | 1117 MapHandleList* transitioned_maps) { |
1135 Label miss; | 1118 Label miss; |
1136 __ JumpIfSmi(receiver(), &miss, Label::kNear); | 1119 __ JumpIfSmi(receiver(), &miss, Label::kNear); |
1137 __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); | 1120 __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); |
1138 for (int i = 0; i < receiver_maps->length(); ++i) { | 1121 for (int i = 0; i < receiver_maps->length(); ++i) { |
1139 __ cmp(scratch1(), receiver_maps->at(i)); | 1122 __ cmp(scratch1(), receiver_maps->at(i)); |
1140 if (transitioned_maps->at(i).is_null()) { | 1123 if (transitioned_maps->at(i).is_null()) { |
1141 __ j(equal, handler_stubs->at(i)); | 1124 __ j(equal, handler_stubs->at(i)); |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1354 // ----------------------------------- | 1337 // ----------------------------------- |
1355 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1338 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1356 } | 1339 } |
1357 | 1340 |
1358 | 1341 |
1359 #undef __ | 1342 #undef __ |
1360 | 1343 |
1361 } } // namespace v8::internal | 1344 } } // namespace v8::internal |
1362 | 1345 |
1363 #endif // V8_TARGET_ARCH_X87 | 1346 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |