OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 r3, | 241 r3, |
242 GetLinkRegisterState(), | 242 GetLinkRegisterState(), |
243 kSaveFPRegs); | 243 kSaveFPRegs); |
244 } | 244 } |
245 } | 245 } |
246 Comment(";;; End allocate local context"); | 246 Comment(";;; End allocate local context"); |
247 } | 247 } |
248 | 248 |
249 // Trace the call. | 249 // Trace the call. |
250 if (FLAG_trace && info()->IsOptimizing()) { | 250 if (FLAG_trace && info()->IsOptimizing()) { |
251 // We have not executed any compiled code yet, so cp still holds the | |
252 // incoming context. | |
251 __ CallRuntime(Runtime::kTraceEnter, 0); | 253 __ CallRuntime(Runtime::kTraceEnter, 0); |
252 } | 254 } |
253 return !is_aborted(); | 255 return !is_aborted(); |
254 } | 256 } |
255 | 257 |
256 | 258 |
257 void LCodeGen::GenerateOsrPrologue() { | 259 void LCodeGen::GenerateOsrPrologue() { |
258 // Generate the OSR entry prologue at the first unknown OSR value, or if there | 260 // Generate the OSR entry prologue at the first unknown OSR value, or if there |
259 // are none, at the OSR entrypoint instruction. | 261 // are none, at the OSR entrypoint instruction. |
260 if (osr_pc_offset_ >= 0) return; | 262 if (osr_pc_offset_ >= 0) return; |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
752 ASSERT(instr != NULL); | 754 ASSERT(instr != NULL); |
753 LPointerMap* pointers = instr->pointer_map(); | 755 LPointerMap* pointers = instr->pointer_map(); |
754 ASSERT(pointers != NULL); | 756 ASSERT(pointers != NULL); |
755 RecordPosition(pointers->position()); | 757 RecordPosition(pointers->position()); |
756 | 758 |
757 __ CallRuntime(function, num_arguments); | 759 __ CallRuntime(function, num_arguments); |
758 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 760 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
759 } | 761 } |
760 | 762 |
761 | 763 |
764 void LCodeGen::LoadContextFromDeferred(LOperand* context) { | |
765 if (context->IsRegister()) { | |
766 __ Move(cp, ToRegister(context)); | |
767 } else if (context->IsStackSlot()) { | |
768 __ ldr(cp, ToMemOperand(context)); | |
769 } else { | |
770 UNREACHABLE(); | |
771 } | |
772 } | |
773 | |
774 | |
762 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 775 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
763 int argc, | 776 int argc, |
764 LInstruction* instr) { | 777 LInstruction* instr, |
778 LOperand* context) { | |
779 LoadContextFromDeferred(context); | |
765 __ CallRuntimeSaveDoubles(id); | 780 __ CallRuntimeSaveDoubles(id); |
766 RecordSafepointWithRegisters( | 781 RecordSafepointWithRegisters( |
767 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); | 782 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); |
768 } | 783 } |
769 | 784 |
770 | 785 |
771 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, | 786 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, |
772 Safepoint::DeoptMode mode) { | 787 Safepoint::DeoptMode mode) { |
773 if (!environment->HasBeenRegistered()) { | 788 if (!environment->HasBeenRegistered()) { |
774 // Physical stack frame layout: | 789 // Physical stack frame layout: |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
970 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 985 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
971 kind, arguments, deopt_mode); | 986 kind, arguments, deopt_mode); |
972 for (int i = 0; i < operands->length(); i++) { | 987 for (int i = 0; i < operands->length(); i++) { |
973 LOperand* pointer = operands->at(i); | 988 LOperand* pointer = operands->at(i); |
974 if (pointer->IsStackSlot()) { | 989 if (pointer->IsStackSlot()) { |
975 safepoint.DefinePointerSlot(pointer->index(), zone()); | 990 safepoint.DefinePointerSlot(pointer->index(), zone()); |
976 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 991 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
977 safepoint.DefinePointerRegister(ToRegister(pointer), zone()); | 992 safepoint.DefinePointerRegister(ToRegister(pointer), zone()); |
978 } | 993 } |
979 } | 994 } |
980 if (kind & Safepoint::kWithRegisters) { | |
981 // Register cp always contains a pointer to the context. | |
982 safepoint.DefinePointerRegister(cp, zone()); | |
983 } | |
984 } | 995 } |
985 | 996 |
986 | 997 |
987 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 998 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
988 Safepoint::DeoptMode deopt_mode) { | 999 Safepoint::DeoptMode deopt_mode) { |
989 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); | 1000 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); |
990 } | 1001 } |
991 | 1002 |
992 | 1003 |
993 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { | 1004 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1066 DoGap(instr); | 1077 DoGap(instr); |
1067 } | 1078 } |
1068 | 1079 |
1069 | 1080 |
1070 void LCodeGen::DoParameter(LParameter* instr) { | 1081 void LCodeGen::DoParameter(LParameter* instr) { |
1071 // Nothing to do. | 1082 // Nothing to do. |
1072 } | 1083 } |
1073 | 1084 |
1074 | 1085 |
1075 void LCodeGen::DoCallStub(LCallStub* instr) { | 1086 void LCodeGen::DoCallStub(LCallStub* instr) { |
1087 ASSERT(ToRegister(instr->context()).is(cp)); | |
1076 ASSERT(ToRegister(instr->result()).is(r0)); | 1088 ASSERT(ToRegister(instr->result()).is(r0)); |
1077 switch (instr->hydrogen()->major_key()) { | 1089 switch (instr->hydrogen()->major_key()) { |
1078 case CodeStub::RegExpConstructResult: { | 1090 case CodeStub::RegExpConstructResult: { |
1079 RegExpConstructResultStub stub; | 1091 RegExpConstructResultStub stub; |
1080 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1092 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
1081 break; | 1093 break; |
1082 } | 1094 } |
1083 case CodeStub::RegExpExec: { | 1095 case CodeStub::RegExpExec: { |
1084 RegExpExecStub stub; | 1096 RegExpExecStub stub; |
1085 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1097 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2016 __ add(scratch, string, Operand(index, LSL, 1)); | 2028 __ add(scratch, string, Operand(index, LSL, 1)); |
2017 __ strh(value, FieldMemOperand(scratch, SeqString::kHeaderSize)); | 2029 __ strh(value, FieldMemOperand(scratch, SeqString::kHeaderSize)); |
2018 } | 2030 } |
2019 } | 2031 } |
2020 } | 2032 } |
2021 | 2033 |
2022 | 2034 |
2023 void LCodeGen::DoThrow(LThrow* instr) { | 2035 void LCodeGen::DoThrow(LThrow* instr) { |
2024 Register input_reg = EmitLoadRegister(instr->value(), ip); | 2036 Register input_reg = EmitLoadRegister(instr->value(), ip); |
2025 __ push(input_reg); | 2037 __ push(input_reg); |
2038 ASSERT(ToRegister(instr->context()).is(cp)); | |
2026 CallRuntime(Runtime::kThrow, 1, instr); | 2039 CallRuntime(Runtime::kThrow, 1, instr); |
2027 | 2040 |
2028 if (FLAG_debug_code) { | 2041 if (FLAG_debug_code) { |
2029 __ stop("Unreachable code."); | 2042 __ stop("Unreachable code."); |
2030 } | 2043 } |
2031 } | 2044 } |
2032 | 2045 |
2033 | 2046 |
2034 void LCodeGen::DoAddI(LAddI* instr) { | 2047 void LCodeGen::DoAddI(LAddI* instr) { |
2035 LOperand* left = instr->left(); | 2048 LOperand* left = instr->left(); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2153 break; | 2166 break; |
2154 } | 2167 } |
2155 default: | 2168 default: |
2156 UNREACHABLE(); | 2169 UNREACHABLE(); |
2157 break; | 2170 break; |
2158 } | 2171 } |
2159 } | 2172 } |
2160 | 2173 |
2161 | 2174 |
2162 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 2175 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
2176 ASSERT(ToRegister(instr->context()).is(cp)); | |
2163 ASSERT(ToRegister(instr->left()).is(r1)); | 2177 ASSERT(ToRegister(instr->left()).is(r1)); |
2164 ASSERT(ToRegister(instr->right()).is(r0)); | 2178 ASSERT(ToRegister(instr->right()).is(r0)); |
2165 ASSERT(ToRegister(instr->result()).is(r0)); | 2179 ASSERT(ToRegister(instr->result()).is(r0)); |
2166 | 2180 |
2167 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 2181 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
2168 // Block literal pool emission to ensure nop indicating no inlined smi code | 2182 // Block literal pool emission to ensure nop indicating no inlined smi code |
2169 // is in the correct position. | 2183 // is in the correct position. |
2170 Assembler::BlockConstPoolScope block_const_pool(masm()); | 2184 Assembler::BlockConstPoolScope block_const_pool(masm()); |
2171 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2185 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
2172 __ nop(); // Signals no inlined code. | 2186 __ nop(); // Signals no inlined code. |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2564 case Token::GTE: | 2578 case Token::GTE: |
2565 return ge; | 2579 return ge; |
2566 default: | 2580 default: |
2567 UNREACHABLE(); | 2581 UNREACHABLE(); |
2568 return kNoCondition; | 2582 return kNoCondition; |
2569 } | 2583 } |
2570 } | 2584 } |
2571 | 2585 |
2572 | 2586 |
2573 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2587 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
2588 ASSERT(ToRegister(instr->context()).is(cp)); | |
2574 Token::Value op = instr->op(); | 2589 Token::Value op = instr->op(); |
2575 | 2590 |
2576 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2591 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2577 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2592 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2578 // This instruction also signals no smi code inlined. | 2593 // This instruction also signals no smi code inlined. |
2579 __ cmp(r0, Operand::Zero()); | 2594 __ cmp(r0, Operand::Zero()); |
2580 | 2595 |
2581 Condition condition = ComputeCompareCondition(op); | 2596 Condition condition = ComputeCompareCondition(op); |
2582 | 2597 |
2583 EmitBranch(instr, condition); | 2598 EmitBranch(instr, condition); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2724 Register reg = ToRegister(instr->value()); | 2739 Register reg = ToRegister(instr->value()); |
2725 Register temp = ToRegister(instr->temp()); | 2740 Register temp = ToRegister(instr->temp()); |
2726 | 2741 |
2727 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2742 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2728 __ cmp(temp, Operand(instr->map())); | 2743 __ cmp(temp, Operand(instr->map())); |
2729 EmitBranch(instr, eq); | 2744 EmitBranch(instr, eq); |
2730 } | 2745 } |
2731 | 2746 |
2732 | 2747 |
2733 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2748 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2749 ASSERT(ToRegister(instr->context()).is(cp)); | |
2734 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. | 2750 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. |
2735 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. | 2751 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. |
2736 | 2752 |
2737 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2753 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
2738 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2754 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
2739 | 2755 |
2740 __ cmp(r0, Operand::Zero()); | 2756 __ cmp(r0, Operand::Zero()); |
2741 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); | 2757 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); |
2742 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); | 2758 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); |
2743 } | 2759 } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2833 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; | 2849 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
2834 flags = static_cast<InstanceofStub::Flags>( | 2850 flags = static_cast<InstanceofStub::Flags>( |
2835 flags | InstanceofStub::kArgsInRegisters); | 2851 flags | InstanceofStub::kArgsInRegisters); |
2836 flags = static_cast<InstanceofStub::Flags>( | 2852 flags = static_cast<InstanceofStub::Flags>( |
2837 flags | InstanceofStub::kCallSiteInlineCheck); | 2853 flags | InstanceofStub::kCallSiteInlineCheck); |
2838 flags = static_cast<InstanceofStub::Flags>( | 2854 flags = static_cast<InstanceofStub::Flags>( |
2839 flags | InstanceofStub::kReturnTrueFalseObject); | 2855 flags | InstanceofStub::kReturnTrueFalseObject); |
2840 InstanceofStub stub(flags); | 2856 InstanceofStub stub(flags); |
2841 | 2857 |
2842 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2858 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
2859 LoadContextFromDeferred(instr->context()); | |
2843 | 2860 |
2844 // Get the temp register reserved by the instruction. This needs to be r4 as | 2861 // Get the temp register reserved by the instruction. This needs to be r4 as |
2845 // its slot of the pushing of safepoint registers is used to communicate the | 2862 // its slot of the pushing of safepoint registers is used to communicate the |
2846 // offset to the location of the map check. | 2863 // offset to the location of the map check. |
2847 Register temp = ToRegister(instr->temp()); | 2864 Register temp = ToRegister(instr->temp()); |
2848 ASSERT(temp.is(r4)); | 2865 ASSERT(temp.is(r4)); |
2849 __ LoadHeapObject(InstanceofStub::right(), instr->function()); | 2866 __ LoadHeapObject(InstanceofStub::right(), instr->function()); |
2850 static const int kAdditionalDelta = 5; | 2867 static const int kAdditionalDelta = 5; |
2851 // Make sure that code size is predicable, since we use specific constants | 2868 // Make sure that code size is predicable, since we use specific constants |
2852 // offsets in the code to find embedded values.. | 2869 // offsets in the code to find embedded values.. |
(...skipping 24 matching lines...) Expand all Loading... | |
2877 | 2894 |
2878 void LCodeGen::DoInstanceSize(LInstanceSize* instr) { | 2895 void LCodeGen::DoInstanceSize(LInstanceSize* instr) { |
2879 Register object = ToRegister(instr->object()); | 2896 Register object = ToRegister(instr->object()); |
2880 Register result = ToRegister(instr->result()); | 2897 Register result = ToRegister(instr->result()); |
2881 __ ldr(result, FieldMemOperand(object, HeapObject::kMapOffset)); | 2898 __ ldr(result, FieldMemOperand(object, HeapObject::kMapOffset)); |
2882 __ ldrb(result, FieldMemOperand(result, Map::kInstanceSizeOffset)); | 2899 __ ldrb(result, FieldMemOperand(result, Map::kInstanceSizeOffset)); |
2883 } | 2900 } |
2884 | 2901 |
2885 | 2902 |
2886 void LCodeGen::DoCmpT(LCmpT* instr) { | 2903 void LCodeGen::DoCmpT(LCmpT* instr) { |
2904 ASSERT(ToRegister(instr->context()).is(cp)); | |
2887 Token::Value op = instr->op(); | 2905 Token::Value op = instr->op(); |
2888 | 2906 |
2889 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2907 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2890 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2908 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2891 // This instruction also signals no smi code inlined. | 2909 // This instruction also signals no smi code inlined. |
2892 __ cmp(r0, Operand::Zero()); | 2910 __ cmp(r0, Operand::Zero()); |
2893 | 2911 |
2894 Condition condition = ComputeCompareCondition(op); | 2912 Condition condition = ComputeCompareCondition(op); |
2895 __ LoadRoot(ToRegister(instr->result()), | 2913 __ LoadRoot(ToRegister(instr->result()), |
2896 Heap::kTrueValueRootIndex, | 2914 Heap::kTrueValueRootIndex, |
2897 condition); | 2915 condition); |
2898 __ LoadRoot(ToRegister(instr->result()), | 2916 __ LoadRoot(ToRegister(instr->result()), |
2899 Heap::kFalseValueRootIndex, | 2917 Heap::kFalseValueRootIndex, |
2900 NegateCondition(condition)); | 2918 NegateCondition(condition)); |
2901 } | 2919 } |
2902 | 2920 |
2903 | 2921 |
2904 void LCodeGen::DoReturn(LReturn* instr) { | 2922 void LCodeGen::DoReturn(LReturn* instr) { |
2905 if (FLAG_trace && info()->IsOptimizing()) { | 2923 if (FLAG_trace && info()->IsOptimizing()) { |
2906 // Push the return value on the stack as the parameter. | 2924 // Push the return value on the stack as the parameter. |
2907 // Runtime::TraceExit returns its parameter in r0. | 2925 // Runtime::TraceExit returns its parameter in r0. We're leaving the code |
2926 // managed by the register allocator and tearing down the frame, it's | |
2927 // safe to write to the context register. | |
2908 __ push(r0); | 2928 __ push(r0); |
2929 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
2909 __ CallRuntime(Runtime::kTraceExit, 1); | 2930 __ CallRuntime(Runtime::kTraceExit, 1); |
2910 } | 2931 } |
2911 if (info()->saves_caller_doubles()) { | 2932 if (info()->saves_caller_doubles()) { |
2912 ASSERT(NeedsEagerFrame()); | 2933 ASSERT(NeedsEagerFrame()); |
2913 BitVector* doubles = chunk()->allocated_double_registers(); | 2934 BitVector* doubles = chunk()->allocated_double_registers(); |
2914 BitVector::Iterator save_iterator(doubles); | 2935 BitVector::Iterator save_iterator(doubles); |
2915 int count = 0; | 2936 int count = 0; |
2916 while (!save_iterator.Done()) { | 2937 while (!save_iterator.Done()) { |
2917 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), | 2938 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
2918 MemOperand(sp, count * kDoubleSize)); | 2939 MemOperand(sp, count * kDoubleSize)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2953 __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset)); | 2974 __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset)); |
2954 if (instr->hydrogen()->RequiresHoleCheck()) { | 2975 if (instr->hydrogen()->RequiresHoleCheck()) { |
2955 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2976 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
2956 __ cmp(result, ip); | 2977 __ cmp(result, ip); |
2957 DeoptimizeIf(eq, instr->environment()); | 2978 DeoptimizeIf(eq, instr->environment()); |
2958 } | 2979 } |
2959 } | 2980 } |
2960 | 2981 |
2961 | 2982 |
2962 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 2983 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
2984 ASSERT(ToRegister(instr->context()).is(cp)); | |
2963 ASSERT(ToRegister(instr->global_object()).is(r0)); | 2985 ASSERT(ToRegister(instr->global_object()).is(r0)); |
2964 ASSERT(ToRegister(instr->result()).is(r0)); | 2986 ASSERT(ToRegister(instr->result()).is(r0)); |
2965 | 2987 |
2966 __ mov(r2, Operand(instr->name())); | 2988 __ mov(r2, Operand(instr->name())); |
2967 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET | 2989 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET |
2968 : RelocInfo::CODE_TARGET_CONTEXT; | 2990 : RelocInfo::CODE_TARGET_CONTEXT; |
2969 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2991 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2970 CallCode(ic, mode, instr); | 2992 CallCode(ic, mode, instr); |
2971 } | 2993 } |
2972 | 2994 |
(...skipping 17 matching lines...) Expand all Loading... | |
2990 DeoptimizeIf(eq, instr->environment()); | 3012 DeoptimizeIf(eq, instr->environment()); |
2991 } | 3013 } |
2992 | 3014 |
2993 // Store the value. | 3015 // Store the value. |
2994 __ str(value, FieldMemOperand(cell, Cell::kValueOffset)); | 3016 __ str(value, FieldMemOperand(cell, Cell::kValueOffset)); |
2995 // Cells are always rescanned, so no write barrier here. | 3017 // Cells are always rescanned, so no write barrier here. |
2996 } | 3018 } |
2997 | 3019 |
2998 | 3020 |
2999 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 3021 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
3022 ASSERT(ToRegister(instr->context()).is(cp)); | |
3000 ASSERT(ToRegister(instr->global_object()).is(r1)); | 3023 ASSERT(ToRegister(instr->global_object()).is(r1)); |
3001 ASSERT(ToRegister(instr->value()).is(r0)); | 3024 ASSERT(ToRegister(instr->value()).is(r0)); |
3002 | 3025 |
3003 __ mov(r2, Operand(instr->name())); | 3026 __ mov(r2, Operand(instr->name())); |
3004 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3027 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3005 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3028 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
3006 : isolate()->builtins()->StoreIC_Initialize(); | 3029 : isolate()->builtins()->StoreIC_Initialize(); |
3007 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 3030 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
3008 } | 3031 } |
3009 | 3032 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3083 if (access.IsInobject()) { | 3106 if (access.IsInobject()) { |
3084 __ ldr(result, FieldMemOperand(object, offset)); | 3107 __ ldr(result, FieldMemOperand(object, offset)); |
3085 } else { | 3108 } else { |
3086 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 3109 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
3087 __ ldr(result, FieldMemOperand(result, offset)); | 3110 __ ldr(result, FieldMemOperand(result, offset)); |
3088 } | 3111 } |
3089 } | 3112 } |
3090 | 3113 |
3091 | 3114 |
3092 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 3115 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
3116 ASSERT(ToRegister(instr->context()).is(cp)); | |
3093 ASSERT(ToRegister(instr->object()).is(r0)); | 3117 ASSERT(ToRegister(instr->object()).is(r0)); |
3094 ASSERT(ToRegister(instr->result()).is(r0)); | 3118 ASSERT(ToRegister(instr->result()).is(r0)); |
3095 | 3119 |
3096 // Name is always in r2. | 3120 // Name is always in r2. |
3097 __ mov(r2, Operand(instr->name())); | 3121 __ mov(r2, Operand(instr->name())); |
3098 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3122 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
3099 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 3123 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
3100 } | 3124 } |
3101 | 3125 |
3102 | 3126 |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3376 if (shift_size >= 0) { | 3400 if (shift_size >= 0) { |
3377 return MemOperand(base, scratch0(), LSL, shift_size); | 3401 return MemOperand(base, scratch0(), LSL, shift_size); |
3378 } else { | 3402 } else { |
3379 ASSERT_EQ(-1, shift_size); | 3403 ASSERT_EQ(-1, shift_size); |
3380 return MemOperand(base, scratch0(), LSR, 1); | 3404 return MemOperand(base, scratch0(), LSR, 1); |
3381 } | 3405 } |
3382 } | 3406 } |
3383 | 3407 |
3384 | 3408 |
3385 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 3409 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
3410 ASSERT(ToRegister(instr->context()).is(cp)); | |
3386 ASSERT(ToRegister(instr->object()).is(r1)); | 3411 ASSERT(ToRegister(instr->object()).is(r1)); |
3387 ASSERT(ToRegister(instr->key()).is(r0)); | 3412 ASSERT(ToRegister(instr->key()).is(r0)); |
3388 | 3413 |
3389 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 3414 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
3390 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 3415 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
3391 } | 3416 } |
3392 | 3417 |
3393 | 3418 |
3394 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 3419 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
3395 Register scratch = scratch0(); | 3420 Register scratch = scratch0(); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3520 ASSERT(instr->HasPointerMap()); | 3545 ASSERT(instr->HasPointerMap()); |
3521 LPointerMap* pointers = instr->pointer_map(); | 3546 LPointerMap* pointers = instr->pointer_map(); |
3522 RecordPosition(pointers->position()); | 3547 RecordPosition(pointers->position()); |
3523 SafepointGenerator safepoint_generator( | 3548 SafepointGenerator safepoint_generator( |
3524 this, pointers, Safepoint::kLazyDeopt); | 3549 this, pointers, Safepoint::kLazyDeopt); |
3525 // The number of arguments is stored in receiver which is r0, as expected | 3550 // The number of arguments is stored in receiver which is r0, as expected |
3526 // by InvokeFunction. | 3551 // by InvokeFunction. |
3527 ParameterCount actual(receiver); | 3552 ParameterCount actual(receiver); |
3528 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3553 __ InvokeFunction(function, actual, CALL_FUNCTION, |
3529 safepoint_generator, CALL_AS_METHOD); | 3554 safepoint_generator, CALL_AS_METHOD); |
3530 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
3531 } | 3555 } |
3532 | 3556 |
3533 | 3557 |
3534 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3558 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3535 LOperand* argument = instr->value(); | 3559 LOperand* argument = instr->value(); |
3536 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3560 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
3537 Abort(kDoPushArgumentNotImplementedForDoubleType); | 3561 Abort(kDoPushArgumentNotImplementedForDoubleType); |
3538 } else { | 3562 } else { |
3539 Register argument_reg = EmitLoadRegister(argument, ip); | 3563 Register argument_reg = EmitLoadRegister(argument, ip); |
3540 __ push(argument_reg); | 3564 __ push(argument_reg); |
3541 } | 3565 } |
3542 } | 3566 } |
3543 | 3567 |
3544 | 3568 |
3545 void LCodeGen::DoDrop(LDrop* instr) { | 3569 void LCodeGen::DoDrop(LDrop* instr) { |
3546 __ Drop(instr->count()); | 3570 __ Drop(instr->count()); |
3547 } | 3571 } |
3548 | 3572 |
3549 | 3573 |
3550 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 3574 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
3551 Register result = ToRegister(instr->result()); | 3575 Register result = ToRegister(instr->result()); |
3552 __ ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3576 __ ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
3553 } | 3577 } |
3554 | 3578 |
3555 | 3579 |
3556 void LCodeGen::DoContext(LContext* instr) { | 3580 void LCodeGen::DoContext(LContext* instr) { |
3557 // If there is a non-return use, the context must be moved to a register. | 3581 // If there is a non-return use, the context must be moved to a register. |
3558 Register result = ToRegister(instr->result()); | 3582 Register result = ToRegister(instr->result()); |
3559 for (HUseIterator it(instr->hydrogen()->uses()); !it.Done(); it.Advance()) { | 3583 if (info()->IsOptimizing()) { |
3560 if (!it.value()->IsReturn()) { | 3584 __ ldr(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3561 __ mov(result, cp); | 3585 } else { |
3562 return; | 3586 // If there is no frame, the context must be in cp. |
3563 } | 3587 ASSERT(result.is(cp)); |
3564 } | 3588 } |
3565 } | 3589 } |
3566 | 3590 |
3567 | 3591 |
3568 void LCodeGen::DoOuterContext(LOuterContext* instr) { | 3592 void LCodeGen::DoOuterContext(LOuterContext* instr) { |
3569 Register context = ToRegister(instr->context()); | 3593 Register context = ToRegister(instr->context()); |
3570 Register result = ToRegister(instr->result()); | 3594 Register result = ToRegister(instr->result()); |
3571 __ ldr(result, | 3595 __ ldr(result, |
3572 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 3596 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
3573 } | 3597 } |
3574 | 3598 |
3575 | 3599 |
3576 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3600 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
3601 ASSERT(ToRegister(instr->context()).is(cp)); | |
3577 __ push(cp); // The context is the first argument. | 3602 __ push(cp); // The context is the first argument. |
3578 __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs()); | 3603 __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs()); |
3579 __ push(scratch0()); | 3604 __ push(scratch0()); |
3580 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); | 3605 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); |
3581 __ push(scratch0()); | 3606 __ push(scratch0()); |
3582 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3607 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
3583 } | 3608 } |
3584 | 3609 |
3585 | 3610 |
3586 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 3611 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
3612 Register context = ToRegister(instr->context()); | |
3587 Register result = ToRegister(instr->result()); | 3613 Register result = ToRegister(instr->result()); |
3588 __ ldr(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 3614 __ ldr(result, ContextOperand(context, Context::GLOBAL_OBJECT_INDEX)); |
3589 } | 3615 } |
3590 | 3616 |
3591 | 3617 |
3592 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 3618 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
3593 Register global = ToRegister(instr->global_object()); | 3619 Register global = ToRegister(instr->global_object()); |
3594 Register result = ToRegister(instr->result()); | 3620 Register result = ToRegister(instr->result()); |
3595 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | 3621 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); |
3596 } | 3622 } |
3597 | 3623 |
3598 | 3624 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3631 | 3657 |
3632 // Set up deoptimization. | 3658 // Set up deoptimization. |
3633 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3659 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
3634 } else { | 3660 } else { |
3635 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3661 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3636 ParameterCount count(arity); | 3662 ParameterCount count(arity); |
3637 ParameterCount expected(formal_parameter_count); | 3663 ParameterCount expected(formal_parameter_count); |
3638 __ InvokeFunction( | 3664 __ InvokeFunction( |
3639 function, expected, count, CALL_FUNCTION, generator, call_kind); | 3665 function, expected, count, CALL_FUNCTION, generator, call_kind); |
3640 } | 3666 } |
3641 | |
3642 // Restore context. | |
3643 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
3644 } | 3667 } |
3645 | 3668 |
3646 | 3669 |
3647 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3670 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
3648 ASSERT(ToRegister(instr->result()).is(r0)); | 3671 ASSERT(ToRegister(instr->result()).is(r0)); |
3649 CallKnownFunction(instr->hydrogen()->function(), | 3672 CallKnownFunction(instr->hydrogen()->function(), |
3650 instr->hydrogen()->formal_parameter_count(), | 3673 instr->hydrogen()->formal_parameter_count(), |
3651 instr->arity(), | 3674 instr->arity(), |
3652 instr, | 3675 instr, |
3653 CALL_AS_METHOD, | 3676 CALL_AS_METHOD, |
3654 R1_UNINITIALIZED); | 3677 R1_UNINITIALIZED); |
3655 } | 3678 } |
3656 | 3679 |
3657 | 3680 |
3658 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3681 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
3682 ASSERT(instr->context() != NULL); | |
3683 ASSERT(ToRegister(instr->context()).is(cp)); | |
ulan
2013/09/27 12:08:00
I think we don't need context in cp here since it
vincent.belliard.fr
2013/09/27 12:37:04
It is just to be consistent with LChunkBuilder::Do
| |
3659 Register input = ToRegister(instr->value()); | 3684 Register input = ToRegister(instr->value()); |
3660 Register result = ToRegister(instr->result()); | 3685 Register result = ToRegister(instr->result()); |
3661 Register scratch = scratch0(); | 3686 Register scratch = scratch0(); |
3662 | 3687 |
3663 // Deoptimize if not a heap number. | 3688 // Deoptimize if not a heap number. |
3664 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3689 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
3665 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3690 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
3666 __ cmp(scratch, Operand(ip)); | 3691 __ cmp(scratch, Operand(ip)); |
3667 DeoptimizeIf(ne, instr->environment()); | 3692 DeoptimizeIf(ne, instr->environment()); |
3668 | 3693 |
(...skipping 23 matching lines...) Expand all Loading... | |
3692 // exponent: floating point exponent value. | 3717 // exponent: floating point exponent value. |
3693 | 3718 |
3694 Label allocated, slow; | 3719 Label allocated, slow; |
3695 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); | 3720 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); |
3696 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); | 3721 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); |
3697 __ b(&allocated); | 3722 __ b(&allocated); |
3698 | 3723 |
3699 // Slow case: Call the runtime system to do the number allocation. | 3724 // Slow case: Call the runtime system to do the number allocation. |
3700 __ bind(&slow); | 3725 __ bind(&slow); |
3701 | 3726 |
3702 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 3727 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr, |
3728 instr->context()); | |
3703 // Set the pointer to the new heap number in tmp. | 3729 // Set the pointer to the new heap number in tmp. |
3704 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0)); | 3730 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0)); |
3705 // Restore input_reg after call to runtime. | 3731 // Restore input_reg after call to runtime. |
3706 __ LoadFromSafepointRegisterSlot(input, input); | 3732 __ LoadFromSafepointRegisterSlot(input, input); |
3707 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 3733 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
3708 | 3734 |
3709 __ bind(&allocated); | 3735 __ bind(&allocated); |
3710 // exponent: floating point exponent value. | 3736 // exponent: floating point exponent value. |
3711 // tmp1: allocated heap number. | 3737 // tmp1: allocated heap number. |
3712 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); | 3738 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3963 Register temp2 = ToRegister(instr->temp2()); | 3989 Register temp2 = ToRegister(instr->temp2()); |
3964 | 3990 |
3965 MathExpGenerator::EmitMathExp( | 3991 MathExpGenerator::EmitMathExp( |
3966 masm(), input, result, double_scratch1, double_scratch2, | 3992 masm(), input, result, double_scratch1, double_scratch2, |
3967 temp1, temp2, scratch0()); | 3993 temp1, temp2, scratch0()); |
3968 } | 3994 } |
3969 | 3995 |
3970 | 3996 |
3971 void LCodeGen::DoMathLog(LMathLog* instr) { | 3997 void LCodeGen::DoMathLog(LMathLog* instr) { |
3972 ASSERT(ToDoubleRegister(instr->result()).is(d2)); | 3998 ASSERT(ToDoubleRegister(instr->result()).is(d2)); |
3999 // Set the context register to a GC-safe fake value. Clobbering it is | |
4000 // OK because this instruction is marked as a call. | |
4001 __ mov(cp, Operand::Zero()); | |
3973 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 4002 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
3974 TranscendentalCacheStub::UNTAGGED); | 4003 TranscendentalCacheStub::UNTAGGED); |
3975 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4004 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
3976 } | 4005 } |
3977 | 4006 |
3978 | 4007 |
3979 void LCodeGen::DoMathTan(LMathTan* instr) { | 4008 void LCodeGen::DoMathTan(LMathTan* instr) { |
3980 ASSERT(ToDoubleRegister(instr->result()).is(d2)); | 4009 ASSERT(ToDoubleRegister(instr->result()).is(d2)); |
4010 // Set the context register to a GC-safe fake value. Clobbering it is | |
4011 // OK because this instruction is marked as a call. | |
4012 __ mov(cp, Operand::Zero()); | |
3981 TranscendentalCacheStub stub(TranscendentalCache::TAN, | 4013 TranscendentalCacheStub stub(TranscendentalCache::TAN, |
3982 TranscendentalCacheStub::UNTAGGED); | 4014 TranscendentalCacheStub::UNTAGGED); |
3983 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4015 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
3984 } | 4016 } |
3985 | 4017 |
3986 | 4018 |
3987 void LCodeGen::DoMathCos(LMathCos* instr) { | 4019 void LCodeGen::DoMathCos(LMathCos* instr) { |
3988 ASSERT(ToDoubleRegister(instr->result()).is(d2)); | 4020 ASSERT(ToDoubleRegister(instr->result()).is(d2)); |
4021 // Set the context register to a GC-safe fake value. Clobbering it is | |
4022 // OK because this instruction is marked as a call. | |
4023 __ mov(cp, Operand::Zero()); | |
3989 TranscendentalCacheStub stub(TranscendentalCache::COS, | 4024 TranscendentalCacheStub stub(TranscendentalCache::COS, |
3990 TranscendentalCacheStub::UNTAGGED); | 4025 TranscendentalCacheStub::UNTAGGED); |
3991 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4026 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
3992 } | 4027 } |
3993 | 4028 |
3994 | 4029 |
3995 void LCodeGen::DoMathSin(LMathSin* instr) { | 4030 void LCodeGen::DoMathSin(LMathSin* instr) { |
3996 ASSERT(ToDoubleRegister(instr->result()).is(d2)); | 4031 ASSERT(ToDoubleRegister(instr->result()).is(d2)); |
4032 // Set the context register to a GC-safe fake value. Clobbering it is | |
4033 // OK because this instruction is marked as a call. | |
4034 __ mov(cp, Operand::Zero()); | |
3997 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 4035 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
3998 TranscendentalCacheStub::UNTAGGED); | 4036 TranscendentalCacheStub::UNTAGGED); |
3999 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4037 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
4000 } | 4038 } |
4001 | 4039 |
4002 | 4040 |
4003 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 4041 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
4042 ASSERT(ToRegister(instr->context()).is(cp)); | |
4004 ASSERT(ToRegister(instr->function()).is(r1)); | 4043 ASSERT(ToRegister(instr->function()).is(r1)); |
4005 ASSERT(instr->HasPointerMap()); | 4044 ASSERT(instr->HasPointerMap()); |
4006 | 4045 |
4007 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 4046 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
4008 if (known_function.is_null()) { | 4047 if (known_function.is_null()) { |
4009 LPointerMap* pointers = instr->pointer_map(); | 4048 LPointerMap* pointers = instr->pointer_map(); |
4010 RecordPosition(pointers->position()); | 4049 RecordPosition(pointers->position()); |
4011 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 4050 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
4012 ParameterCount count(instr->arity()); | 4051 ParameterCount count(instr->arity()); |
4013 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 4052 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
4014 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
4015 } else { | 4053 } else { |
4016 CallKnownFunction(known_function, | 4054 CallKnownFunction(known_function, |
4017 instr->hydrogen()->formal_parameter_count(), | 4055 instr->hydrogen()->formal_parameter_count(), |
4018 instr->arity(), | 4056 instr->arity(), |
4019 instr, | 4057 instr, |
4020 CALL_AS_METHOD, | 4058 CALL_AS_METHOD, |
4021 R1_CONTAINS_TARGET); | 4059 R1_CONTAINS_TARGET); |
4022 } | 4060 } |
4023 } | 4061 } |
4024 | 4062 |
4025 | 4063 |
4026 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 4064 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
4065 ASSERT(ToRegister(instr->context()).is(cp)); | |
4027 ASSERT(ToRegister(instr->result()).is(r0)); | 4066 ASSERT(ToRegister(instr->result()).is(r0)); |
4028 | 4067 |
4029 int arity = instr->arity(); | 4068 int arity = instr->arity(); |
4030 Handle<Code> ic = | 4069 Handle<Code> ic = |
4031 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | 4070 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); |
4032 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4071 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
4033 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
4034 } | 4072 } |
4035 | 4073 |
4036 | 4074 |
4037 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 4075 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
4076 ASSERT(ToRegister(instr->context()).is(cp)); | |
4038 ASSERT(ToRegister(instr->result()).is(r0)); | 4077 ASSERT(ToRegister(instr->result()).is(r0)); |
4039 | 4078 |
4040 int arity = instr->arity(); | 4079 int arity = instr->arity(); |
4041 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 4080 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
4042 Handle<Code> ic = | 4081 Handle<Code> ic = |
4043 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4082 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
4044 __ mov(r2, Operand(instr->name())); | 4083 __ mov(r2, Operand(instr->name())); |
4045 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); | 4084 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); |
4046 // Restore context register. | |
4047 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
4048 } | 4085 } |
4049 | 4086 |
4050 | 4087 |
4051 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4088 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
4089 ASSERT(ToRegister(instr->context()).is(cp)); | |
4052 ASSERT(ToRegister(instr->function()).is(r1)); | 4090 ASSERT(ToRegister(instr->function()).is(r1)); |
4053 ASSERT(ToRegister(instr->result()).is(r0)); | 4091 ASSERT(ToRegister(instr->result()).is(r0)); |
4054 | 4092 |
4055 int arity = instr->arity(); | 4093 int arity = instr->arity(); |
4056 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 4094 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
4057 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4095 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
4058 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
4059 } | 4096 } |
4060 | 4097 |
4061 | 4098 |
4062 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 4099 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
4100 ASSERT(ToRegister(instr->context()).is(cp)); | |
4063 ASSERT(ToRegister(instr->result()).is(r0)); | 4101 ASSERT(ToRegister(instr->result()).is(r0)); |
4064 | 4102 |
4065 int arity = instr->arity(); | 4103 int arity = instr->arity(); |
4066 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 4104 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
4067 Handle<Code> ic = | 4105 Handle<Code> ic = |
4068 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4106 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
4069 __ mov(r2, Operand(instr->name())); | 4107 __ mov(r2, Operand(instr->name())); |
4070 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); | 4108 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); |
4071 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
4072 } | 4109 } |
4073 | 4110 |
4074 | 4111 |
4075 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 4112 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
4076 ASSERT(ToRegister(instr->result()).is(r0)); | 4113 ASSERT(ToRegister(instr->result()).is(r0)); |
4077 CallKnownFunction(instr->hydrogen()->target(), | 4114 CallKnownFunction(instr->hydrogen()->target(), |
4078 instr->hydrogen()->formal_parameter_count(), | 4115 instr->hydrogen()->formal_parameter_count(), |
4079 instr->arity(), | 4116 instr->arity(), |
4080 instr, | 4117 instr, |
4081 CALL_AS_FUNCTION, | 4118 CALL_AS_FUNCTION, |
4082 R1_UNINITIALIZED); | 4119 R1_UNINITIALIZED); |
4083 } | 4120 } |
4084 | 4121 |
4085 | 4122 |
4086 void LCodeGen::DoCallNew(LCallNew* instr) { | 4123 void LCodeGen::DoCallNew(LCallNew* instr) { |
4124 ASSERT(ToRegister(instr->context()).is(cp)); | |
4087 ASSERT(ToRegister(instr->constructor()).is(r1)); | 4125 ASSERT(ToRegister(instr->constructor()).is(r1)); |
4088 ASSERT(ToRegister(instr->result()).is(r0)); | 4126 ASSERT(ToRegister(instr->result()).is(r0)); |
4089 | 4127 |
4090 __ mov(r0, Operand(instr->arity())); | 4128 __ mov(r0, Operand(instr->arity())); |
4091 // No cell in r2 for construct type feedback in optimized code | 4129 // No cell in r2 for construct type feedback in optimized code |
4092 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 4130 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
4093 __ mov(r2, Operand(undefined_value)); | 4131 __ mov(r2, Operand(undefined_value)); |
4094 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 4132 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
4095 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4133 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
4096 } | 4134 } |
4097 | 4135 |
4098 | 4136 |
4099 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 4137 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
4138 ASSERT(ToRegister(instr->context()).is(cp)); | |
4100 ASSERT(ToRegister(instr->constructor()).is(r1)); | 4139 ASSERT(ToRegister(instr->constructor()).is(r1)); |
4101 ASSERT(ToRegister(instr->result()).is(r0)); | 4140 ASSERT(ToRegister(instr->result()).is(r0)); |
4102 | 4141 |
4103 __ mov(r0, Operand(instr->arity())); | 4142 __ mov(r0, Operand(instr->arity())); |
4104 __ mov(r2, Operand(instr->hydrogen()->property_cell())); | 4143 __ mov(r2, Operand(instr->hydrogen()->property_cell())); |
4105 ElementsKind kind = instr->hydrogen()->elements_kind(); | 4144 ElementsKind kind = instr->hydrogen()->elements_kind(); |
4106 AllocationSiteOverrideMode override_mode = | 4145 AllocationSiteOverrideMode override_mode = |
4107 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 4146 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
4108 ? DISABLE_ALLOCATION_SITES | 4147 ? DISABLE_ALLOCATION_SITES |
4109 : DONT_OVERRIDE; | 4148 : DONT_OVERRIDE; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4241 GetLinkRegisterState(), | 4280 GetLinkRegisterState(), |
4242 kSaveFPRegs, | 4281 kSaveFPRegs, |
4243 EMIT_REMEMBERED_SET, | 4282 EMIT_REMEMBERED_SET, |
4244 check_needed); | 4283 check_needed); |
4245 } | 4284 } |
4246 } | 4285 } |
4247 } | 4286 } |
4248 | 4287 |
4249 | 4288 |
4250 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4289 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
4290 ASSERT(ToRegister(instr->context()).is(cp)); | |
4251 ASSERT(ToRegister(instr->object()).is(r1)); | 4291 ASSERT(ToRegister(instr->object()).is(r1)); |
4252 ASSERT(ToRegister(instr->value()).is(r0)); | 4292 ASSERT(ToRegister(instr->value()).is(r0)); |
4253 | 4293 |
4254 // Name is always in r2. | 4294 // Name is always in r2. |
4255 __ mov(r2, Operand(instr->name())); | 4295 __ mov(r2, Operand(instr->name())); |
4256 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4296 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
4257 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4297 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
4258 : isolate()->builtins()->StoreIC_Initialize(); | 4298 : isolate()->builtins()->StoreIC_Initialize(); |
4259 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4299 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
4260 } | 4300 } |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4464 DoStoreKeyedExternalArray(instr); | 4504 DoStoreKeyedExternalArray(instr); |
4465 } else if (instr->hydrogen()->value()->representation().IsDouble()) { | 4505 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
4466 DoStoreKeyedFixedDoubleArray(instr); | 4506 DoStoreKeyedFixedDoubleArray(instr); |
4467 } else { | 4507 } else { |
4468 DoStoreKeyedFixedArray(instr); | 4508 DoStoreKeyedFixedArray(instr); |
4469 } | 4509 } |
4470 } | 4510 } |
4471 | 4511 |
4472 | 4512 |
4473 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 4513 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
4514 ASSERT(ToRegister(instr->context()).is(cp)); | |
4474 ASSERT(ToRegister(instr->object()).is(r2)); | 4515 ASSERT(ToRegister(instr->object()).is(r2)); |
4475 ASSERT(ToRegister(instr->key()).is(r1)); | 4516 ASSERT(ToRegister(instr->key()).is(r1)); |
4476 ASSERT(ToRegister(instr->value()).is(r0)); | 4517 ASSERT(ToRegister(instr->value()).is(r0)); |
4477 | 4518 |
4478 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4519 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
4479 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4520 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
4480 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4521 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
4481 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4522 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
4482 } | 4523 } |
4483 | 4524 |
(...skipping 13 matching lines...) Expand all Loading... | |
4497 __ b(ne, ¬_applicable); | 4538 __ b(ne, ¬_applicable); |
4498 | 4539 |
4499 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4540 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
4500 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4541 Register new_map_reg = ToRegister(instr->new_map_temp()); |
4501 __ mov(new_map_reg, Operand(to_map)); | 4542 __ mov(new_map_reg, Operand(to_map)); |
4502 __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4543 __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
4503 // Write barrier. | 4544 // Write barrier. |
4504 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 4545 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
4505 scratch, GetLinkRegisterState(), kDontSaveFPRegs); | 4546 scratch, GetLinkRegisterState(), kDontSaveFPRegs); |
4506 } else { | 4547 } else { |
4548 ASSERT(ToRegister(instr->context()).is(cp)); | |
4507 PushSafepointRegistersScope scope( | 4549 PushSafepointRegistersScope scope( |
4508 this, Safepoint::kWithRegistersAndDoubles); | 4550 this, Safepoint::kWithRegistersAndDoubles); |
4509 __ Move(r0, object_reg); | 4551 __ Move(r0, object_reg); |
4510 __ Move(r1, to_map); | 4552 __ Move(r1, to_map); |
4511 TransitionElementsKindStub stub(from_kind, to_kind); | 4553 TransitionElementsKindStub stub(from_kind, to_kind); |
4512 __ CallStub(&stub); | 4554 __ CallStub(&stub); |
4513 RecordSafepointWithRegistersAndDoubles( | 4555 RecordSafepointWithRegistersAndDoubles( |
4514 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4556 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4515 } | 4557 } |
4516 __ bind(¬_applicable); | 4558 __ bind(¬_applicable); |
4517 } | 4559 } |
4518 | 4560 |
4519 | 4561 |
4520 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4562 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
4521 Register object = ToRegister(instr->object()); | 4563 Register object = ToRegister(instr->object()); |
4522 Register temp = ToRegister(instr->temp()); | 4564 Register temp = ToRegister(instr->temp()); |
4523 __ TestJSArrayForAllocationMemento(object, temp); | 4565 __ TestJSArrayForAllocationMemento(object, temp); |
4524 DeoptimizeIf(eq, instr->environment()); | 4566 DeoptimizeIf(eq, instr->environment()); |
4525 } | 4567 } |
4526 | 4568 |
4527 | 4569 |
4528 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4570 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
4571 ASSERT(ToRegister(instr->context()).is(cp)); | |
4529 __ push(ToRegister(instr->left())); | 4572 __ push(ToRegister(instr->left())); |
4530 __ push(ToRegister(instr->right())); | 4573 __ push(ToRegister(instr->right())); |
4531 StringAddStub stub(instr->hydrogen()->flags()); | 4574 StringAddStub stub(instr->hydrogen()->flags()); |
4532 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4575 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
4533 } | 4576 } |
4534 | 4577 |
4535 | 4578 |
4536 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4579 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
4537 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { | 4580 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
4538 public: | 4581 public: |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4574 // DoStringCharCodeAt above. | 4617 // DoStringCharCodeAt above. |
4575 if (instr->index()->IsConstantOperand()) { | 4618 if (instr->index()->IsConstantOperand()) { |
4576 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 4619 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
4577 __ mov(scratch, Operand(Smi::FromInt(const_index))); | 4620 __ mov(scratch, Operand(Smi::FromInt(const_index))); |
4578 __ push(scratch); | 4621 __ push(scratch); |
4579 } else { | 4622 } else { |
4580 Register index = ToRegister(instr->index()); | 4623 Register index = ToRegister(instr->index()); |
4581 __ SmiTag(index); | 4624 __ SmiTag(index); |
4582 __ push(index); | 4625 __ push(index); |
4583 } | 4626 } |
4584 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 4627 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr, |
4628 instr->context()); | |
4585 __ AssertSmi(r0); | 4629 __ AssertSmi(r0); |
4586 __ SmiUntag(r0); | 4630 __ SmiUntag(r0); |
4587 __ StoreToSafepointRegisterSlot(r0, result); | 4631 __ StoreToSafepointRegisterSlot(r0, result); |
4588 } | 4632 } |
4589 | 4633 |
4590 | 4634 |
4591 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 4635 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
4592 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { | 4636 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { |
4593 public: | 4637 public: |
4594 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 4638 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4626 Register result = ToRegister(instr->result()); | 4670 Register result = ToRegister(instr->result()); |
4627 | 4671 |
4628 // TODO(3095996): Get rid of this. For now, we need to make the | 4672 // TODO(3095996): Get rid of this. For now, we need to make the |
4629 // result register contain a valid pointer because it is already | 4673 // result register contain a valid pointer because it is already |
4630 // contained in the register pointer map. | 4674 // contained in the register pointer map. |
4631 __ mov(result, Operand::Zero()); | 4675 __ mov(result, Operand::Zero()); |
4632 | 4676 |
4633 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4677 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4634 __ SmiTag(char_code); | 4678 __ SmiTag(char_code); |
4635 __ push(char_code); | 4679 __ push(char_code); |
4636 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 4680 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
4637 __ StoreToSafepointRegisterSlot(r0, result); | 4681 __ StoreToSafepointRegisterSlot(r0, result); |
4638 } | 4682 } |
4639 | 4683 |
4640 | 4684 |
4641 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4685 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4642 LOperand* input = instr->value(); | 4686 LOperand* input = instr->value(); |
4643 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4687 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4644 LOperand* output = instr->result(); | 4688 LOperand* output = instr->result(); |
4645 ASSERT(output->IsDoubleRegister()); | 4689 ASSERT(output->IsDoubleRegister()); |
4646 SwVfpRegister single_scratch = double_scratch0().low(); | 4690 SwVfpRegister single_scratch = double_scratch0().low(); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4765 } | 4809 } |
4766 | 4810 |
4767 // Slow case: Call the runtime system to do the number allocation. | 4811 // Slow case: Call the runtime system to do the number allocation. |
4768 __ bind(&slow); | 4812 __ bind(&slow); |
4769 | 4813 |
4770 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 4814 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
4771 // register is stored, as this register is in the pointer map, but contains an | 4815 // register is stored, as this register is in the pointer map, but contains an |
4772 // integer value. | 4816 // integer value. |
4773 __ mov(ip, Operand::Zero()); | 4817 __ mov(ip, Operand::Zero()); |
4774 __ StoreToSafepointRegisterSlot(ip, dst); | 4818 __ StoreToSafepointRegisterSlot(ip, dst); |
4775 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4819 // NumberTagI and NumberTagD use the context from the frame, rather than |
4820 // the environment's HContext or HInlinedContext value. | |
4821 // They only call Runtime::kAllocateHeapNumber. | |
4822 // The corresponding HChange instructions are added in a phase that does | |
4823 // not have easy access to the local context. | |
4824 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
4825 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | |
4826 RecordSafepointWithRegisters( | |
4827 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | |
4776 __ Move(dst, r0); | 4828 __ Move(dst, r0); |
4777 __ sub(dst, dst, Operand(kHeapObjectTag)); | 4829 __ sub(dst, dst, Operand(kHeapObjectTag)); |
4778 | 4830 |
4779 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4831 // Done. Put the value in dbl_scratch into the value of the allocated heap |
4780 // number. | 4832 // number. |
4781 __ bind(&done); | 4833 __ bind(&done); |
4782 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); | 4834 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); |
4783 __ add(dst, dst, Operand(kHeapObjectTag)); | 4835 __ add(dst, dst, Operand(kHeapObjectTag)); |
4784 __ StoreToSafepointRegisterSlot(dst, dst); | 4836 __ StoreToSafepointRegisterSlot(dst, dst); |
4785 } | 4837 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4821 | 4873 |
4822 | 4874 |
4823 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4875 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
4824 // TODO(3095996): Get rid of this. For now, we need to make the | 4876 // TODO(3095996): Get rid of this. For now, we need to make the |
4825 // result register contain a valid pointer because it is already | 4877 // result register contain a valid pointer because it is already |
4826 // contained in the register pointer map. | 4878 // contained in the register pointer map. |
4827 Register reg = ToRegister(instr->result()); | 4879 Register reg = ToRegister(instr->result()); |
4828 __ mov(reg, Operand::Zero()); | 4880 __ mov(reg, Operand::Zero()); |
4829 | 4881 |
4830 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4882 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4831 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4883 // NumberTagI and NumberTagD use the context from the frame, rather than |
4884 // the environment's HContext or HInlinedContext value. | |
4885 // They only call Runtime::kAllocateHeapNumber. | |
4886 // The corresponding HChange instructions are added in a phase that does | |
4887 // not have easy access to the local context. | |
4888 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
4889 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | |
4890 RecordSafepointWithRegisters( | |
4891 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | |
4832 __ sub(r0, r0, Operand(kHeapObjectTag)); | 4892 __ sub(r0, r0, Operand(kHeapObjectTag)); |
4833 __ StoreToSafepointRegisterSlot(r0, reg); | 4893 __ StoreToSafepointRegisterSlot(r0, reg); |
4834 } | 4894 } |
4835 | 4895 |
4836 | 4896 |
4837 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4897 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4838 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4898 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
4839 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value())); | 4899 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value())); |
4840 } | 4900 } |
4841 | 4901 |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5150 __ cmp(reg, Operand(object)); | 5210 __ cmp(reg, Operand(object)); |
5151 } | 5211 } |
5152 DeoptimizeIf(ne, instr->environment()); | 5212 DeoptimizeIf(ne, instr->environment()); |
5153 } | 5213 } |
5154 | 5214 |
5155 | 5215 |
5156 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5216 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
5157 { | 5217 { |
5158 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5218 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
5159 __ push(object); | 5219 __ push(object); |
5160 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); | 5220 __ mov(cp, Operand::Zero()); |
5221 __ CallRuntimeSaveDoubles(Runtime::kMigrateInstance); | |
5222 RecordSafepointWithRegisters( | |
5223 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | |
5161 __ StoreToSafepointRegisterSlot(r0, scratch0()); | 5224 __ StoreToSafepointRegisterSlot(r0, scratch0()); |
5162 } | 5225 } |
5163 __ tst(scratch0(), Operand(kSmiTagMask)); | 5226 __ tst(scratch0(), Operand(kSmiTagMask)); |
5164 DeoptimizeIf(eq, instr->environment()); | 5227 DeoptimizeIf(eq, instr->environment()); |
5165 } | 5228 } |
5166 | 5229 |
5167 | 5230 |
5168 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5231 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
5169 class DeferredCheckMaps V8_FINAL : public LDeferredCode { | 5232 class DeferredCheckMaps V8_FINAL : public LDeferredCode { |
5170 public: | 5233 public: |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5353 __ SmiTag(size); | 5416 __ SmiTag(size); |
5354 __ push(size); | 5417 __ push(size); |
5355 } else { | 5418 } else { |
5356 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5419 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
5357 __ Push(Smi::FromInt(size)); | 5420 __ Push(Smi::FromInt(size)); |
5358 } | 5421 } |
5359 | 5422 |
5360 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5423 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
5361 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5424 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
5362 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5425 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
5363 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); | 5426 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr, |
5427 instr->context()); | |
5364 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5428 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
5365 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5429 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
5366 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); | 5430 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr, |
5431 instr->context()); | |
5367 } else { | 5432 } else { |
5368 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); | 5433 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr, |
5434 instr->context()); | |
5369 } | 5435 } |
5370 __ StoreToSafepointRegisterSlot(r0, result); | 5436 __ StoreToSafepointRegisterSlot(r0, result); |
5371 } | 5437 } |
5372 | 5438 |
5373 | 5439 |
5374 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5440 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
5375 ASSERT(ToRegister(instr->value()).is(r0)); | 5441 ASSERT(ToRegister(instr->value()).is(r0)); |
5376 __ push(r0); | 5442 __ push(r0); |
5377 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5443 CallRuntime(Runtime::kToFastProperties, 1, instr); |
5378 } | 5444 } |
5379 | 5445 |
5380 | 5446 |
5381 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5447 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
5448 ASSERT(ToRegister(instr->context()).is(cp)); | |
5382 Label materialized; | 5449 Label materialized; |
5383 // Registers will be used as follows: | 5450 // Registers will be used as follows: |
5384 // r6 = literals array. | 5451 // r6 = literals array. |
5385 // r1 = regexp literal. | 5452 // r1 = regexp literal. |
5386 // r0 = regexp literal clone. | 5453 // r0 = regexp literal clone. |
5387 // r2-5 are used as temporaries. | 5454 // r2-5 are used as temporaries. |
5388 int literal_offset = | 5455 int literal_offset = |
5389 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); | 5456 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
5390 __ LoadHeapObject(r6, instr->hydrogen()->literals()); | 5457 __ LoadHeapObject(r6, instr->hydrogen()->literals()); |
5391 __ ldr(r1, FieldMemOperand(r6, literal_offset)); | 5458 __ ldr(r1, FieldMemOperand(r6, literal_offset)); |
(...skipping 23 matching lines...) Expand all Loading... | |
5415 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 5482 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
5416 __ pop(r1); | 5483 __ pop(r1); |
5417 | 5484 |
5418 __ bind(&allocated); | 5485 __ bind(&allocated); |
5419 // Copy the content into the newly allocated memory. | 5486 // Copy the content into the newly allocated memory. |
5420 __ CopyFields(r0, r1, double_scratch0(), size / kPointerSize); | 5487 __ CopyFields(r0, r1, double_scratch0(), size / kPointerSize); |
5421 } | 5488 } |
5422 | 5489 |
5423 | 5490 |
5424 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 5491 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
5492 ASSERT(ToRegister(instr->context()).is(cp)); | |
5425 // Use the fast case closure allocation code that allocates in new | 5493 // Use the fast case closure allocation code that allocates in new |
5426 // space for nested functions that don't need literals cloning. | 5494 // space for nested functions that don't need literals cloning. |
5427 bool pretenure = instr->hydrogen()->pretenure(); | 5495 bool pretenure = instr->hydrogen()->pretenure(); |
5428 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5496 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
5429 FastNewClosureStub stub(instr->hydrogen()->language_mode(), | 5497 FastNewClosureStub stub(instr->hydrogen()->language_mode(), |
5430 instr->hydrogen()->is_generator()); | 5498 instr->hydrogen()->is_generator()); |
5431 __ mov(r2, Operand(instr->hydrogen()->shared_info())); | 5499 __ mov(r2, Operand(instr->hydrogen()->shared_info())); |
5432 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 5500 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
5433 } else { | 5501 } else { |
5434 __ mov(r2, Operand(instr->hydrogen()->shared_info())); | 5502 __ mov(r2, Operand(instr->hydrogen()->shared_info())); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5609 } | 5677 } |
5610 | 5678 |
5611 | 5679 |
5612 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5680 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
5613 // Nothing to see here, move on! | 5681 // Nothing to see here, move on! |
5614 } | 5682 } |
5615 | 5683 |
5616 | 5684 |
5617 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5685 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
5618 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5686 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
5687 LoadContextFromDeferred(instr->context()); | |
5619 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5688 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
5620 RecordSafepointWithLazyDeopt( | 5689 RecordSafepointWithLazyDeopt( |
5621 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 5690 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
5622 ASSERT(instr->HasEnvironment()); | 5691 ASSERT(instr->HasEnvironment()); |
5623 LEnvironment* env = instr->environment(); | 5692 LEnvironment* env = instr->environment(); |
5624 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5693 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
5625 } | 5694 } |
5626 | 5695 |
5627 | 5696 |
5628 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 5697 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
(...skipping 13 matching lines...) Expand all Loading... | |
5642 LEnvironment* env = instr->environment(); | 5711 LEnvironment* env = instr->environment(); |
5643 // There is no LLazyBailout instruction for stack-checks. We have to | 5712 // There is no LLazyBailout instruction for stack-checks. We have to |
5644 // prepare for lazy deoptimization explicitly here. | 5713 // prepare for lazy deoptimization explicitly here. |
5645 if (instr->hydrogen()->is_function_entry()) { | 5714 if (instr->hydrogen()->is_function_entry()) { |
5646 // Perform stack overflow check. | 5715 // Perform stack overflow check. |
5647 Label done; | 5716 Label done; |
5648 __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 5717 __ LoadRoot(ip, Heap::kStackLimitRootIndex); |
5649 __ cmp(sp, Operand(ip)); | 5718 __ cmp(sp, Operand(ip)); |
5650 __ b(hs, &done); | 5719 __ b(hs, &done); |
5651 PredictableCodeSizeScope predictable(masm_, 2 * Assembler::kInstrSize); | 5720 PredictableCodeSizeScope predictable(masm_, 2 * Assembler::kInstrSize); |
5721 ASSERT(instr->context()->IsRegister()); | |
5722 ASSERT(ToRegister(instr->context()).is(cp)); | |
5652 CallCode(isolate()->builtins()->StackCheck(), | 5723 CallCode(isolate()->builtins()->StackCheck(), |
5653 RelocInfo::CODE_TARGET, | 5724 RelocInfo::CODE_TARGET, |
5654 instr); | 5725 instr); |
5655 EnsureSpaceForLazyDeopt(); | 5726 EnsureSpaceForLazyDeopt(); |
5656 last_lazy_deopt_pc_ = masm()->pc_offset(); | 5727 last_lazy_deopt_pc_ = masm()->pc_offset(); |
5657 __ bind(&done); | 5728 __ bind(&done); |
5658 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5729 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
5659 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5730 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
5660 } else { | 5731 } else { |
5661 ASSERT(instr->hydrogen()->is_backwards_branch()); | 5732 ASSERT(instr->hydrogen()->is_backwards_branch()); |
5662 // Perform stack overflow check if this goto needs it before jumping. | 5733 // Perform stack overflow check if this goto needs it before jumping. |
5663 DeferredStackCheck* deferred_stack_check = | 5734 DeferredStackCheck* deferred_stack_check = |
5664 new(zone()) DeferredStackCheck(this, instr); | 5735 new(zone()) DeferredStackCheck(this, instr); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5782 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5853 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5783 __ ldr(result, FieldMemOperand(scratch, | 5854 __ ldr(result, FieldMemOperand(scratch, |
5784 FixedArray::kHeaderSize - kPointerSize)); | 5855 FixedArray::kHeaderSize - kPointerSize)); |
5785 __ bind(&done); | 5856 __ bind(&done); |
5786 } | 5857 } |
5787 | 5858 |
5788 | 5859 |
5789 #undef __ | 5860 #undef __ |
5790 | 5861 |
5791 } } // namespace v8::internal | 5862 } } // namespace v8::internal |
OLD | NEW |