| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include "a64/lithium-codegen-a64.h" | 30 #include "a64/lithium-codegen-a64.h" |
| 31 #include "a64/lithium-gap-resolver-a64.h" | 31 #include "a64/lithium-gap-resolver-a64.h" |
| 32 #include "code-stubs.h" | 32 #include "code-stubs.h" |
| 33 #include "stub-cache.h" | 33 #include "stub-cache.h" |
| 34 #include "hydrogen-osr.h" | 34 #include "hydrogen-osr.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 | 39 |
| 40 class SafepointGenerator : public CallWrapper { | 40 class SafepointGenerator V8_FINAL : public CallWrapper { |
| 41 public: | 41 public: |
| 42 SafepointGenerator(LCodeGen* codegen, | 42 SafepointGenerator(LCodeGen* codegen, |
| 43 LPointerMap* pointers, | 43 LPointerMap* pointers, |
| 44 Safepoint::DeoptMode mode) | 44 Safepoint::DeoptMode mode) |
| 45 : codegen_(codegen), | 45 : codegen_(codegen), |
| 46 pointers_(pointers), | 46 pointers_(pointers), |
| 47 deopt_mode_(mode) { } | 47 deopt_mode_(mode) { } |
| 48 virtual ~SafepointGenerator() { } | 48 virtual ~SafepointGenerator() { } |
| 49 | 49 |
| 50 virtual void BeforeCall(int call_size) const { } | 50 virtual void BeforeCall(int call_size) const { } |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 RelocInfo::Mode mode, | 405 RelocInfo::Mode mode, |
| 406 LInstruction* instr) { | 406 LInstruction* instr) { |
| 407 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); | 407 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
| 408 } | 408 } |
| 409 | 409 |
| 410 | 410 |
| 411 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 411 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 412 RelocInfo::Mode mode, | 412 RelocInfo::Mode mode, |
| 413 LInstruction* instr, | 413 LInstruction* instr, |
| 414 SafepointMode safepoint_mode) { | 414 SafepointMode safepoint_mode) { |
| 415 EnsureSpaceForLazyDeopt(); | 415 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 416 ASSERT(instr != NULL); | 416 ASSERT(instr != NULL); |
| 417 | 417 |
| 418 Assembler::BlockConstPoolScope scope(masm_); | 418 Assembler::BlockConstPoolScope scope(masm_); |
| 419 LPointerMap* pointers = instr->pointer_map(); | 419 LPointerMap* pointers = instr->pointer_map(); |
| 420 RecordPosition(pointers->position()); | 420 RecordPosition(pointers->position()); |
| 421 __ Call(code, mode); | 421 __ Call(code, mode); |
| 422 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 422 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
| 423 | 423 |
| 424 if ((code->kind() == Code::BINARY_OP_IC) || | 424 if ((code->kind() == Code::BINARY_OP_IC) || |
| 425 (code->kind() == Code::COMPARE_IC)) { | 425 (code->kind() == Code::COMPARE_IC)) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); | 498 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); |
| 499 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 499 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 500 } | 500 } |
| 501 | 501 |
| 502 ASSERT(ToRegister(instr->result()).is(x0)); | 502 ASSERT(ToRegister(instr->result()).is(x0)); |
| 503 } | 503 } |
| 504 | 504 |
| 505 | 505 |
| 506 void LCodeGen::CallRuntime(const Runtime::Function* function, | 506 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 507 int num_arguments, | 507 int num_arguments, |
| 508 LInstruction* instr) { | 508 LInstruction* instr, |
| 509 SaveFPRegsMode save_doubles) { |
| 509 ASSERT(instr != NULL); | 510 ASSERT(instr != NULL); |
| 510 LPointerMap* pointers = instr->pointer_map(); | 511 LPointerMap* pointers = instr->pointer_map(); |
| 511 ASSERT(pointers != NULL); | 512 ASSERT(pointers != NULL); |
| 512 RecordPosition(pointers->position()); | 513 RecordPosition(pointers->position()); |
| 513 | 514 |
| 514 __ CallRuntime(function, num_arguments); | 515 __ CallRuntime(function, num_arguments, save_doubles); |
| 516 |
| 515 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 517 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 516 } | 518 } |
| 517 | 519 |
| 518 | 520 |
| 519 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 521 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 520 int argc, | 522 int argc, |
| 521 LInstruction* instr) { | 523 LInstruction* instr) { |
| 522 __ CallRuntimeSaveDoubles(id); | 524 __ CallRuntimeSaveDoubles(id); |
| 523 RecordSafepointWithRegisters( | 525 RecordSafepointWithRegisters( |
| 524 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); | 526 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 osr_pc_offset_ = masm()->pc_offset(); | 743 osr_pc_offset_ = masm()->pc_offset(); |
| 742 | 744 |
| 743 // Adjust the frame size, subsuming the unoptimized frame into the | 745 // Adjust the frame size, subsuming the unoptimized frame into the |
| 744 // optimized frame. | 746 // optimized frame. |
| 745 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); | 747 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); |
| 746 ASSERT(slots >= 0); | 748 ASSERT(slots >= 0); |
| 747 __ Claim(slots); | 749 __ Claim(slots); |
| 748 } | 750 } |
| 749 | 751 |
| 750 | 752 |
| 751 bool LCodeGen::GenerateBody() { | |
| 752 ASSERT(is_generating()); | |
| 753 bool emit_instructions = true; | |
| 754 | |
| 755 for (current_instruction_ = 0; | |
| 756 !is_aborted() && (current_instruction_ < instructions_->length()); | |
| 757 current_instruction_++) { | |
| 758 LInstruction* instr = instructions_->at(current_instruction_); | |
| 759 | |
| 760 // Don't emit code for basic blocks with a replacement. | |
| 761 if (instr->IsLabel()) { | |
| 762 emit_instructions = !LLabel::cast(instr)->HasReplacement(); | |
| 763 } | |
| 764 if (!emit_instructions) continue; | |
| 765 | |
| 766 if (FLAG_code_comments && instr->HasInterestingComment(this)) { | |
| 767 Comment(";;; <@%d,#%d> %s", | |
| 768 current_instruction_, | |
| 769 instr->hydrogen_value()->id(), | |
| 770 instr->Mnemonic()); | |
| 771 } | |
| 772 | |
| 773 RecordAndUpdatePosition(instr->position()); | |
| 774 | |
| 775 instr->CompileToNative(this); | |
| 776 } | |
| 777 EnsureSpaceForLazyDeopt(); | |
| 778 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 779 return !is_aborted(); | |
| 780 } | |
| 781 | |
| 782 | |
| 783 bool LCodeGen::GenerateDeferredCode() { | 753 bool LCodeGen::GenerateDeferredCode() { |
| 784 ASSERT(is_generating()); | 754 ASSERT(is_generating()); |
| 785 if (deferred_.length() > 0) { | 755 if (deferred_.length() > 0) { |
| 786 for (int i = 0; !is_aborted() && (i < deferred_.length()); i++) { | 756 for (int i = 0; !is_aborted() && (i < deferred_.length()); i++) { |
| 787 LDeferredCode* code = deferred_[i]; | 757 LDeferredCode* code = deferred_[i]; |
| 788 | 758 |
| 789 int pos = instructions_->at(code->instruction_index())->position(); | 759 int pos = instructions_->at(code->instruction_index())->position(); |
| 790 RecordAndUpdatePosition(pos); | 760 RecordAndUpdatePosition(pos); |
| 791 | 761 |
| 792 Comment(";;; <@%d,#%d> " | 762 Comment(";;; <@%d,#%d> " |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 info()->CommitDependencies(code); | 835 info()->CommitDependencies(code); |
| 866 } | 836 } |
| 867 | 837 |
| 868 | 838 |
| 869 void LCodeGen::Abort(BailoutReason reason) { | 839 void LCodeGen::Abort(BailoutReason reason) { |
| 870 info()->set_bailout_reason(reason); | 840 info()->set_bailout_reason(reason); |
| 871 status_ = ABORTED; | 841 status_ = ABORTED; |
| 872 } | 842 } |
| 873 | 843 |
| 874 | 844 |
| 875 void LCodeGen::Comment(const char* format, ...) { | |
| 876 if (!FLAG_code_comments) return; | |
| 877 char buffer[4 * KB]; | |
| 878 StringBuilder builder(buffer, ARRAY_SIZE(buffer)); | |
| 879 va_list arguments; | |
| 880 va_start(arguments, format); | |
| 881 builder.AddFormattedList(format, arguments); | |
| 882 va_end(arguments); | |
| 883 | |
| 884 // Copy the string before recording it in the assembler to avoid | |
| 885 // issues when the stack allocated buffer goes out of scope. | |
| 886 size_t length = builder.position(); | |
| 887 Vector<char> copy = Vector<char>::New(length + 1); | |
| 888 memcpy(copy.start(), builder.Finalize(), copy.length()); | |
| 889 masm()->RecordComment(copy.start()); | |
| 890 } | |
| 891 | |
| 892 | |
| 893 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | 845 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { |
| 894 ZoneList<Handle<Map> > maps(1, zone()); | 846 ZoneList<Handle<Map> > maps(1, zone()); |
| 847 ZoneList<Handle<JSObject> > objects(1, zone()); |
| 895 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 848 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 896 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 849 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
| 897 RelocInfo::Mode mode = it.rinfo()->rmode(); | 850 if (Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) { |
| 898 if (mode == RelocInfo::EMBEDDED_OBJECT && | 851 if (it.rinfo()->target_object()->IsMap()) { |
| 899 it.rinfo()->target_object()->IsMap()) { | 852 Handle<Map> map(Map::cast(it.rinfo()->target_object())); |
| 900 Handle<Map> map(Map::cast(it.rinfo()->target_object())); | |
| 901 if (map->CanTransition()) { | |
| 902 maps.Add(map, zone()); | 853 maps.Add(map, zone()); |
| 854 } else if (it.rinfo()->target_object()->IsJSObject()) { |
| 855 Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object())); |
| 856 objects.Add(object, zone()); |
| 903 } | 857 } |
| 904 } | 858 } |
| 905 } | 859 } |
| 906 #ifdef VERIFY_HEAP | 860 #ifdef VERIFY_HEAP |
| 907 // This disables verification of weak embedded maps after full GC. | 861 // This disables verification of weak embedded objects after full GC. |
| 908 // AddDependentCode can cause a GC, which would observe the state where | 862 // AddDependentCode can cause a GC, which would observe the state where |
| 909 // this code is not yet in the depended code lists of the embedded maps. | 863 // this code is not yet in the depended code lists of the embedded maps. |
| 910 NoWeakEmbeddedMapsVerificationScope disable_verification_of_embedded_maps; | 864 NoWeakObjectVerificationScope disable_verification_of_embedded_objects; |
| 911 #endif | 865 #endif |
| 912 for (int i = 0; i < maps.length(); i++) { | 866 for (int i = 0; i < maps.length(); i++) { |
| 913 maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code); | 867 maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code); |
| 914 } | 868 } |
| 869 for (int i = 0; i < objects.length(); i++) { |
| 870 AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code); |
| 871 } |
| 915 } | 872 } |
| 916 | 873 |
| 917 | 874 |
| 918 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 875 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 919 int length = deoptimizations_.length(); | 876 int length = deoptimizations_.length(); |
| 920 if (length == 0) return; | 877 if (length == 0) return; |
| 921 | 878 |
| 922 Handle<DeoptimizationInputData> data = | 879 Handle<DeoptimizationInputData> data = |
| 923 factory()->NewDeoptimizationInputData(length, TENURED); | 880 factory()->NewDeoptimizationInputData(length, TENURED); |
| 924 | 881 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1076 void LCodeGen::DeoptimizeIfNotRoot(Register rt, | 1033 void LCodeGen::DeoptimizeIfNotRoot(Register rt, |
| 1077 Heap::RootListIndex index, | 1034 Heap::RootListIndex index, |
| 1078 LEnvironment* environment) { | 1035 LEnvironment* environment) { |
| 1079 Label dont_deopt; | 1036 Label dont_deopt; |
| 1080 __ JumpIfRoot(rt, index, &dont_deopt); | 1037 __ JumpIfRoot(rt, index, &dont_deopt); |
| 1081 Deoptimize(environment); | 1038 Deoptimize(environment); |
| 1082 __ Bind(&dont_deopt); | 1039 __ Bind(&dont_deopt); |
| 1083 } | 1040 } |
| 1084 | 1041 |
| 1085 | 1042 |
| 1086 void LCodeGen::EnsureSpaceForLazyDeopt() { | 1043 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { |
| 1087 if (info()->IsStub()) return; | 1044 if (info()->IsStub()) return; |
| 1088 // Ensure that we have enough space after the previous lazy-bailout | 1045 // Ensure that we have enough space after the previous lazy-bailout |
| 1089 // instruction for patching the code here. | 1046 // instruction for patching the code here. |
| 1090 intptr_t current_pc = masm()->pc_offset(); | 1047 intptr_t current_pc = masm()->pc_offset(); |
| 1091 int patch_size = Deoptimizer::patch_size(); | |
| 1092 | 1048 |
| 1093 if (current_pc < (last_lazy_deopt_pc_ + patch_size)) { | 1049 if (current_pc < (last_lazy_deopt_pc_ + space_needed)) { |
| 1094 intptr_t padding_size = last_lazy_deopt_pc_ + patch_size - current_pc; | 1050 ptrdiff_t padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
| 1095 ASSERT((padding_size % kInstructionSize) == 0); | 1051 ASSERT((padding_size % kInstructionSize) == 0); |
| 1096 InstructionAccurateScope instruction_accurate( | 1052 InstructionAccurateScope instruction_accurate( |
| 1097 masm(), padding_size / kInstructionSize); | 1053 masm(), padding_size / kInstructionSize); |
| 1098 | 1054 |
| 1099 while (padding_size > 0) { | 1055 while (padding_size > 0) { |
| 1100 __ nop(); | 1056 __ nop(); |
| 1101 padding_size -= kInstructionSize; | 1057 padding_size -= kInstructionSize; |
| 1102 } | 1058 } |
| 1103 } | 1059 } |
| 1104 } | 1060 } |
| (...skipping 1346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2451 __ Ldr(temp, FieldMemOperand(temp, Cell::kValueOffset)); | 2407 __ Ldr(temp, FieldMemOperand(temp, Cell::kValueOffset)); |
| 2452 __ Cmp(reg, temp); | 2408 __ Cmp(reg, temp); |
| 2453 } else { | 2409 } else { |
| 2454 __ Cmp(reg, Operand(object)); | 2410 __ Cmp(reg, Operand(object)); |
| 2455 } | 2411 } |
| 2456 DeoptimizeIf(ne, instr->environment()); | 2412 DeoptimizeIf(ne, instr->environment()); |
| 2457 } | 2413 } |
| 2458 | 2414 |
| 2459 | 2415 |
| 2460 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 2416 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
| 2461 EnsureSpaceForLazyDeopt(); | 2417 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 2462 last_lazy_deopt_pc_ = masm()->pc_offset(); | 2418 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 2463 ASSERT(instr->HasEnvironment()); | 2419 ASSERT(instr->HasEnvironment()); |
| 2464 LEnvironment* env = instr->environment(); | 2420 LEnvironment* env = instr->environment(); |
| 2465 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 2421 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 2466 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2422 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 2467 } | 2423 } |
| 2468 | 2424 |
| 2469 | 2425 |
| 2470 void LCodeGen::DoDateField(LDateField* instr) { | 2426 void LCodeGen::DoDateField(LDateField* instr) { |
| 2471 Register object = ToRegister(instr->date()); | 2427 Register object = ToRegister(instr->date()); |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2805 } | 2761 } |
| 2806 | 2762 |
| 2807 | 2763 |
| 2808 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 2764 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
| 2809 Register global = ToRegister(instr->global_object()); | 2765 Register global = ToRegister(instr->global_object()); |
| 2810 Register result = ToRegister(instr->result()); | 2766 Register result = ToRegister(instr->result()); |
| 2811 __ Ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | 2767 __ Ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); |
| 2812 } | 2768 } |
| 2813 | 2769 |
| 2814 | 2770 |
| 2815 int LCodeGen::GetNextEmittedBlock() const { | |
| 2816 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | |
| 2817 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | |
| 2818 } | |
| 2819 return -1; | |
| 2820 } | |
| 2821 | |
| 2822 | |
| 2823 void LCodeGen::EmitGoto(int block) { | 2771 void LCodeGen::EmitGoto(int block) { |
| 2824 // Do not emit jump if we are emitting a goto to the next block. | 2772 // Do not emit jump if we are emitting a goto to the next block. |
| 2825 if (!IsNextEmittedBlock(block)) { | 2773 if (!IsNextEmittedBlock(block)) { |
| 2826 __ B(chunk_->GetAssemblyLabel(LookupDestination(block))); | 2774 __ B(chunk_->GetAssemblyLabel(LookupDestination(block))); |
| 2827 } | 2775 } |
| 2828 } | 2776 } |
| 2829 | 2777 |
| 2830 | 2778 |
| 2831 void LCodeGen::DoGoto(LGoto* instr) { | 2779 void LCodeGen::DoGoto(LGoto* instr) { |
| 2832 EmitGoto(instr->block_id()); | 2780 EmitGoto(instr->block_id()); |
| (...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3504 } | 3452 } |
| 3505 | 3453 |
| 3506 | 3454 |
| 3507 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 3455 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 3508 HObjectAccess access = instr->hydrogen()->access(); | 3456 HObjectAccess access = instr->hydrogen()->access(); |
| 3509 int offset = access.offset(); | 3457 int offset = access.offset(); |
| 3510 Register object = ToRegister(instr->object()); | 3458 Register object = ToRegister(instr->object()); |
| 3511 | 3459 |
| 3512 if (access.IsExternalMemory()) { | 3460 if (access.IsExternalMemory()) { |
| 3513 Register result = ToRegister(instr->result()); | 3461 Register result = ToRegister(instr->result()); |
| 3514 __ Ldr(result, MemOperand(object, offset)); | 3462 // TODO(all): Does this need an Integer32 accessor? |
| 3463 if (access.representation().IsByte()) { |
| 3464 __ Ldrb(result, MemOperand(object, offset)); |
| 3465 } else { |
| 3466 __ Ldr(result, MemOperand(object, offset)); |
| 3467 } |
| 3515 return; | 3468 return; |
| 3516 } | 3469 } |
| 3517 | 3470 |
| 3518 if (instr->hydrogen()->representation().IsDouble()) { | 3471 if (instr->hydrogen()->representation().IsDouble()) { |
| 3519 FPRegister result = ToDoubleRegister(instr->result()); | 3472 FPRegister result = ToDoubleRegister(instr->result()); |
| 3520 __ Ldr(result, FieldMemOperand(object, offset)); | 3473 __ Ldr(result, FieldMemOperand(object, offset)); |
| 3474 return; |
| 3475 } |
| 3476 |
| 3477 Register result = ToRegister(instr->result()); |
| 3478 Register source; |
| 3479 if (access.IsInobject()) { |
| 3480 source = object; |
| 3521 } else { | 3481 } else { |
| 3522 Register result = ToRegister(instr->result()); | 3482 // Load the properties array, using result as a scratch register. |
| 3523 Register src = no_reg; | 3483 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 3524 if (access.IsInobject()) { | 3484 source = result; |
| 3525 src = object; | 3485 } |
| 3526 } else { | 3486 if (access.representation().IsByte()) { |
| 3527 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 3487 __ Ldrb(result, FieldMemOperand(source, offset)); |
| 3528 src = result; | 3488 } else if (access.representation().IsInteger32()) { |
| 3529 } | 3489 __ Ldr(result.W(), FieldMemOperand(source, offset)); |
| 3530 if (access.representation().IsInteger32()) { | 3490 } else { |
| 3531 __ Ldr(result.W(), FieldMemOperand(src, offset)); | 3491 __ Ldr(result, FieldMemOperand(source, offset)); |
| 3532 } else { | |
| 3533 __ Ldr(result, FieldMemOperand(src, offset)); | |
| 3534 } | |
| 3535 } | 3492 } |
| 3536 } | 3493 } |
| 3537 | 3494 |
| 3538 | 3495 |
| 3539 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 3496 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 3540 // LoadIC expects x2 to hold the name, and x0 to hold the receiver. | 3497 // LoadIC expects x2 to hold the name, and x0 to hold the receiver. |
| 3541 ASSERT(ToRegister(instr->object()).is(x0)); | 3498 ASSERT(ToRegister(instr->object()).is(x0)); |
| 3542 __ Mov(x2, Operand(instr->name())); | 3499 __ Mov(x2, Operand(instr->name())); |
| 3543 | 3500 |
| 3544 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3501 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| (...skipping 1131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4676 // Perform stack overflow check. | 4633 // Perform stack overflow check. |
| 4677 Label done; | 4634 Label done; |
| 4678 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); | 4635 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); |
| 4679 __ B(hs, &done); | 4636 __ B(hs, &done); |
| 4680 | 4637 |
| 4681 // TODO(bafsa): Make sure that the EnsureSpaceForLazyDeopt inside | 4638 // TODO(bafsa): Make sure that the EnsureSpaceForLazyDeopt inside |
| 4682 // CallCodeGeneric will not insert any nop while calling the stub by | 4639 // CallCodeGeneric will not insert any nop while calling the stub by |
| 4683 // inserting them now. The EnsureSpaceForLazyDeopt in CallCodeGeneric | 4640 // inserting them now. The EnsureSpaceForLazyDeopt in CallCodeGeneric |
| 4684 // will go away at some point during the rebase (r18642) so this will become | 4641 // will go away at some point during the rebase (r18642) so this will become |
| 4685 // unecessary and should be removed at this point. | 4642 // unecessary and should be removed at this point. |
| 4686 EnsureSpaceForLazyDeopt(); | 4643 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 4687 | 4644 |
| 4688 PredictableCodeSizeScope predictable(masm_, | 4645 PredictableCodeSizeScope predictable(masm_, |
| 4689 Assembler::kCallSizeWithRelocation); | 4646 Assembler::kCallSizeWithRelocation); |
| 4690 CallCode(isolate()->builtins()->StackCheck(), | 4647 CallCode(isolate()->builtins()->StackCheck(), |
| 4691 RelocInfo::CODE_TARGET, | 4648 RelocInfo::CODE_TARGET, |
| 4692 instr); | 4649 instr); |
| 4693 EnsureSpaceForLazyDeopt(); | 4650 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 4694 last_lazy_deopt_pc_ = masm()->pc_offset(); | 4651 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 4695 | 4652 |
| 4696 __ Bind(&done); | 4653 __ Bind(&done); |
| 4697 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 4654 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 4698 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 4655 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 4699 } else { | 4656 } else { |
| 4700 ASSERT(instr->hydrogen()->is_backwards_branch()); | 4657 ASSERT(instr->hydrogen()->is_backwards_branch()); |
| 4701 // Perform stack overflow check if this goto needs it before jumping. | 4658 // Perform stack overflow check if this goto needs it before jumping. |
| 4702 DeferredStackCheck* deferred_stack_check = | 4659 DeferredStackCheck* deferred_stack_check = |
| 4703 new(zone()) DeferredStackCheck(this, instr); | 4660 new(zone()) DeferredStackCheck(this, instr); |
| 4704 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); | 4661 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); |
| 4705 __ B(lo, deferred_stack_check->entry()); | 4662 __ B(lo, deferred_stack_check->entry()); |
| 4706 | 4663 |
| 4707 EnsureSpaceForLazyDeopt(); | 4664 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 4708 last_lazy_deopt_pc_ = masm()->pc_offset(); | 4665 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 4709 __ Bind(instr->done_label()); | 4666 __ Bind(instr->done_label()); |
| 4710 deferred_stack_check->SetExit(instr->done_label()); | 4667 deferred_stack_check->SetExit(instr->done_label()); |
| 4711 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 4668 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 4712 // Don't record a deoptimization index for the safepoint here. | 4669 // Don't record a deoptimization index for the safepoint here. |
| 4713 // This will be done explicitly when emitting call and the safepoint in | 4670 // This will be done explicitly when emitting call and the safepoint in |
| 4714 // the deferred code. | 4671 // the deferred code. |
| 4715 } | 4672 } |
| 4716 } | 4673 } |
| 4717 | 4674 |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4946 Representation representation = instr->representation(); | 4903 Representation representation = instr->representation(); |
| 4947 | 4904 |
| 4948 Register object = ToRegister(instr->object()); | 4905 Register object = ToRegister(instr->object()); |
| 4949 Register temp0 = ToRegister(instr->temp0()); | 4906 Register temp0 = ToRegister(instr->temp0()); |
| 4950 Register temp1 = ToRegister(instr->temp1()); | 4907 Register temp1 = ToRegister(instr->temp1()); |
| 4951 HObjectAccess access = instr->hydrogen()->access(); | 4908 HObjectAccess access = instr->hydrogen()->access(); |
| 4952 int offset = access.offset(); | 4909 int offset = access.offset(); |
| 4953 | 4910 |
| 4954 if (access.IsExternalMemory()) { | 4911 if (access.IsExternalMemory()) { |
| 4955 Register value = ToRegister(instr->value()); | 4912 Register value = ToRegister(instr->value()); |
| 4956 __ Str(value, MemOperand(object, offset)); | 4913 if (representation.IsByte()) { |
| 4914 __ Strb(value, MemOperand(object, offset)); |
| 4915 } else { |
| 4916 __ Str(value, MemOperand(object, offset)); |
| 4917 } |
| 4957 return; | 4918 return; |
| 4958 } | 4919 } |
| 4959 | 4920 |
| 4960 Handle<Map> transition = instr->transition(); | 4921 Handle<Map> transition = instr->transition(); |
| 4961 | 4922 |
| 4962 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4923 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 4963 Register value = ToRegister(instr->value()); | 4924 Register value = ToRegister(instr->value()); |
| 4964 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4925 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4965 DeoptimizeIfSmi(value, instr->environment()); | 4926 DeoptimizeIfSmi(value, instr->environment()); |
| 4966 } | 4927 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4986 temp1, | 4947 temp1, |
| 4987 GetLinkRegisterState(), | 4948 GetLinkRegisterState(), |
| 4988 kSaveFPRegs, | 4949 kSaveFPRegs, |
| 4989 OMIT_REMEMBERED_SET, | 4950 OMIT_REMEMBERED_SET, |
| 4990 OMIT_SMI_CHECK); | 4951 OMIT_SMI_CHECK); |
| 4991 } | 4952 } |
| 4992 } | 4953 } |
| 4993 | 4954 |
| 4994 // Do the store. | 4955 // Do the store. |
| 4995 Register value = ToRegister(instr->value()); | 4956 Register value = ToRegister(instr->value()); |
| 4996 Register dst = no_reg; | 4957 Register destination; |
| 4997 SmiCheck check_needed = | 4958 SmiCheck check_needed = |
| 4998 instr->hydrogen()->value()->IsHeapObject() | 4959 instr->hydrogen()->value()->IsHeapObject() |
| 4999 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4960 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 5000 if (access.IsInobject()) { | 4961 if (access.IsInobject()) { |
| 5001 dst = object; | 4962 destination = object; |
| 5002 } else { | 4963 } else { |
| 5003 __ Ldr(temp0, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 4964 __ Ldr(temp0, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 5004 dst = temp0; | 4965 destination = temp0; |
| 5005 } | 4966 } |
| 5006 if (access.representation().IsInteger32()) { | 4967 if (representation.IsByte()) { |
| 5007 __ Str(value.W(), FieldMemOperand(dst, offset)); | 4968 __ Strb(value, FieldMemOperand(destination, offset)); |
| 4969 } else if (access.representation().IsInteger32()) { |
| 4970 __ Str(value.W(), FieldMemOperand(destination, offset)); |
| 5008 } else { | 4971 } else { |
| 5009 __ Str(value, FieldMemOperand(dst, offset)); | 4972 __ Str(value, FieldMemOperand(destination, offset)); |
| 5010 } | 4973 } |
| 5011 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4974 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 5012 __ RecordWriteField(dst, | 4975 __ RecordWriteField(destination, |
| 5013 offset, | 4976 offset, |
| 5014 value, // Clobbered. | 4977 value, // Clobbered. |
| 5015 temp1, // Clobbered. | 4978 temp1, // Clobbered. |
| 5016 GetLinkRegisterState(), | 4979 GetLinkRegisterState(), |
| 5017 kSaveFPRegs, | 4980 kSaveFPRegs, |
| 5018 EMIT_REMEMBERED_SET, | 4981 EMIT_REMEMBERED_SET, |
| 5019 check_needed); | 4982 check_needed); |
| 5020 } | 4983 } |
| 5021 } | 4984 } |
| 5022 | 4985 |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5597 __ Bind(&out_of_object); | 5560 __ Bind(&out_of_object); |
| 5598 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5561 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 5599 // Index is equal to negated out of object property index plus 1. | 5562 // Index is equal to negated out of object property index plus 1. |
| 5600 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5563 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 5601 __ Ldr(result, FieldMemOperand(result, | 5564 __ Ldr(result, FieldMemOperand(result, |
| 5602 FixedArray::kHeaderSize - kPointerSize)); | 5565 FixedArray::kHeaderSize - kPointerSize)); |
| 5603 __ Bind(&done); | 5566 __ Bind(&done); |
| 5604 } | 5567 } |
| 5605 | 5568 |
| 5606 } } // namespace v8::internal | 5569 } } // namespace v8::internal |
| OLD | NEW |