OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 | 75 |
76 | 76 |
77 #define __ masm()-> | 77 #define __ masm()-> |
78 | 78 |
79 bool LCodeGen::GenerateCode() { | 79 bool LCodeGen::GenerateCode() { |
80 HPhase phase("Code generation", chunk()); | 80 HPhase phase("Code generation", chunk()); |
81 ASSERT(is_unused()); | 81 ASSERT(is_unused()); |
82 status_ = GENERATING; | 82 status_ = GENERATING; |
83 CpuFeatures::Scope scope1(VFP3); | 83 CpuFeatures::Scope scope1(VFP3); |
84 CpuFeatures::Scope scope2(ARMv7); | 84 CpuFeatures::Scope scope2(ARMv7); |
| 85 |
| 86 CodeStub::GenerateFPStubs(); |
| 87 |
| 88 // Open a frame scope to indicate that there is a frame on the stack. The |
| 89 // NONE indicates that the scope shouldn't actually generate code to set up |
| 90 // the frame (that is done in GeneratePrologue). |
| 91 FrameScope frame_scope(masm_, StackFrame::NONE); |
| 92 |
85 return GeneratePrologue() && | 93 return GeneratePrologue() && |
86 GenerateBody() && | 94 GenerateBody() && |
87 GenerateDeferredCode() && | 95 GenerateDeferredCode() && |
88 GenerateDeoptJumpTable() && | 96 GenerateDeoptJumpTable() && |
89 GenerateSafepointTable(); | 97 GenerateSafepointTable(); |
90 } | 98 } |
91 | 99 |
92 | 100 |
93 void LCodeGen::FinishCode(Handle<Code> code) { | 101 void LCodeGen::FinishCode(Handle<Code> code) { |
94 ASSERT(is_done()); | 102 ASSERT(is_done()); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 // Copy any necessary parameters into the context. | 207 // Copy any necessary parameters into the context. |
200 int num_parameters = scope()->num_parameters(); | 208 int num_parameters = scope()->num_parameters(); |
201 for (int i = 0; i < num_parameters; i++) { | 209 for (int i = 0; i < num_parameters; i++) { |
202 Variable* var = scope()->parameter(i); | 210 Variable* var = scope()->parameter(i); |
203 if (var->IsContextSlot()) { | 211 if (var->IsContextSlot()) { |
204 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 212 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
205 (num_parameters - 1 - i) * kPointerSize; | 213 (num_parameters - 1 - i) * kPointerSize; |
206 // Load parameter from stack. | 214 // Load parameter from stack. |
207 __ ldr(r0, MemOperand(fp, parameter_offset)); | 215 __ ldr(r0, MemOperand(fp, parameter_offset)); |
208 // Store it in the context. | 216 // Store it in the context. |
209 __ mov(r1, Operand(Context::SlotOffset(var->index()))); | 217 MemOperand target = ContextOperand(cp, var->index()); |
210 __ str(r0, MemOperand(cp, r1)); | 218 __ str(r0, target); |
211 // Update the write barrier. This clobbers all involved | 219 // Update the write barrier. This clobbers r3 and r0. |
212 // registers, so we have to use two more registers to avoid | 220 __ RecordWriteContextSlot( |
213 // clobbering cp. | 221 cp, target.offset(), r0, r3, kLRHasBeenSaved, kSaveFPRegs); |
214 __ mov(r2, Operand(cp)); | |
215 __ RecordWrite(r2, Operand(r1), r3, r0); | |
216 } | 222 } |
217 } | 223 } |
218 Comment(";;; End allocate local context"); | 224 Comment(";;; End allocate local context"); |
219 } | 225 } |
220 | 226 |
221 // Trace the call. | 227 // Trace the call. |
222 if (FLAG_trace) { | 228 if (FLAG_trace) { |
223 __ CallRuntime(Runtime::kTraceEnter, 0); | 229 __ CallRuntime(Runtime::kTraceEnter, 0); |
224 } | 230 } |
225 return !is_aborted(); | 231 return !is_aborted(); |
(...skipping 29 matching lines...) Expand all Loading... |
255 } | 261 } |
256 } | 262 } |
257 | 263 |
258 | 264 |
259 bool LCodeGen::GenerateDeferredCode() { | 265 bool LCodeGen::GenerateDeferredCode() { |
260 ASSERT(is_generating()); | 266 ASSERT(is_generating()); |
261 if (deferred_.length() > 0) { | 267 if (deferred_.length() > 0) { |
262 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 268 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
263 LDeferredCode* code = deferred_[i]; | 269 LDeferredCode* code = deferred_[i]; |
264 __ bind(code->entry()); | 270 __ bind(code->entry()); |
| 271 Comment(";;; Deferred code @%d: %s.", |
| 272 code->instruction_index(), |
| 273 code->instr()->Mnemonic()); |
265 code->Generate(); | 274 code->Generate(); |
266 __ jmp(code->exit()); | 275 __ jmp(code->exit()); |
267 } | 276 } |
268 | 277 |
269 // Pad code to ensure that the last piece of deferred code have | 278 // Pad code to ensure that the last piece of deferred code have |
270 // room for lazy bailout. | 279 // room for lazy bailout. |
271 while ((masm()->pc_offset() - LastSafepointEnd()) | 280 while ((masm()->pc_offset() - LastSafepointEnd()) |
272 < Deoptimizer::patch_size()) { | 281 < Deoptimizer::patch_size()) { |
273 __ nop(); | 282 __ nop(); |
274 } | 283 } |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 } | 741 } |
733 | 742 |
734 | 743 |
735 void LCodeGen::RecordSafepoint( | 744 void LCodeGen::RecordSafepoint( |
736 LPointerMap* pointers, | 745 LPointerMap* pointers, |
737 Safepoint::Kind kind, | 746 Safepoint::Kind kind, |
738 int arguments, | 747 int arguments, |
739 int deoptimization_index) { | 748 int deoptimization_index) { |
740 ASSERT(expected_safepoint_kind_ == kind); | 749 ASSERT(expected_safepoint_kind_ == kind); |
741 | 750 |
742 const ZoneList<LOperand*>* operands = pointers->operands(); | 751 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); |
743 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 752 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
744 kind, arguments, deoptimization_index); | 753 kind, arguments, deoptimization_index); |
745 for (int i = 0; i < operands->length(); i++) { | 754 for (int i = 0; i < operands->length(); i++) { |
746 LOperand* pointer = operands->at(i); | 755 LOperand* pointer = operands->at(i); |
747 if (pointer->IsStackSlot()) { | 756 if (pointer->IsStackSlot()) { |
748 safepoint.DefinePointerSlot(pointer->index()); | 757 safepoint.DefinePointerSlot(pointer->index()); |
749 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 758 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
750 safepoint.DefinePointerRegister(ToRegister(pointer)); | 759 safepoint.DefinePointerRegister(ToRegister(pointer)); |
751 } | 760 } |
752 } | 761 } |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1025 | 1034 |
1026 | 1035 |
1027 void LCodeGen::DoDivI(LDivI* instr) { | 1036 void LCodeGen::DoDivI(LDivI* instr) { |
1028 class DeferredDivI: public LDeferredCode { | 1037 class DeferredDivI: public LDeferredCode { |
1029 public: | 1038 public: |
1030 DeferredDivI(LCodeGen* codegen, LDivI* instr) | 1039 DeferredDivI(LCodeGen* codegen, LDivI* instr) |
1031 : LDeferredCode(codegen), instr_(instr) { } | 1040 : LDeferredCode(codegen), instr_(instr) { } |
1032 virtual void Generate() { | 1041 virtual void Generate() { |
1033 codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV); | 1042 codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV); |
1034 } | 1043 } |
| 1044 virtual LInstruction* instr() { return instr_; } |
1035 private: | 1045 private: |
1036 LDivI* instr_; | 1046 LDivI* instr_; |
1037 }; | 1047 }; |
1038 | 1048 |
1039 const Register left = ToRegister(instr->InputAt(0)); | 1049 const Register left = ToRegister(instr->InputAt(0)); |
1040 const Register right = ToRegister(instr->InputAt(1)); | 1050 const Register right = ToRegister(instr->InputAt(1)); |
1041 const Register scratch = scratch0(); | 1051 const Register scratch = scratch0(); |
1042 const Register result = ToRegister(instr->result()); | 1052 const Register result = ToRegister(instr->result()); |
1043 | 1053 |
1044 // Check for x / 0. | 1054 // Check for x / 0. |
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1736 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 1746 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
1737 Register left = ToRegister(instr->InputAt(0)); | 1747 Register left = ToRegister(instr->InputAt(0)); |
1738 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1748 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1739 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1749 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1740 | 1750 |
1741 __ cmp(left, Operand(instr->hydrogen()->right())); | 1751 __ cmp(left, Operand(instr->hydrogen()->right())); |
1742 EmitBranch(true_block, false_block, eq); | 1752 EmitBranch(true_block, false_block, eq); |
1743 } | 1753 } |
1744 | 1754 |
1745 | 1755 |
1746 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1756 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { |
1747 Register scratch = scratch0(); | 1757 Register scratch = scratch0(); |
1748 Register reg = ToRegister(instr->InputAt(0)); | 1758 Register reg = ToRegister(instr->InputAt(0)); |
| 1759 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1749 | 1760 |
1750 // TODO(fsc): If the expression is known to be a smi, then it's | 1761 // If the expression is known to be untagged or a smi, then it's definitely |
1751 // definitely not null. Jump to the false block. | 1762 // not null, and it can't be a an undetectable object. |
| 1763 if (instr->hydrogen()->representation().IsSpecialization() || |
| 1764 instr->hydrogen()->type().IsSmi()) { |
| 1765 EmitGoto(false_block); |
| 1766 return; |
| 1767 } |
1752 | 1768 |
1753 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1769 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1754 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1770 Heap::RootListIndex nil_value = instr->nil() == kNullValue ? |
1755 | 1771 Heap::kNullValueRootIndex : |
1756 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1772 Heap::kUndefinedValueRootIndex; |
| 1773 __ LoadRoot(ip, nil_value); |
1757 __ cmp(reg, ip); | 1774 __ cmp(reg, ip); |
1758 if (instr->is_strict()) { | 1775 if (instr->kind() == kStrictEquality) { |
1759 EmitBranch(true_block, false_block, eq); | 1776 EmitBranch(true_block, false_block, eq); |
1760 } else { | 1777 } else { |
| 1778 Heap::RootListIndex other_nil_value = instr->nil() == kNullValue ? |
| 1779 Heap::kUndefinedValueRootIndex : |
| 1780 Heap::kNullValueRootIndex; |
1761 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1781 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1762 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1782 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1763 __ b(eq, true_label); | 1783 __ b(eq, true_label); |
1764 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1784 __ LoadRoot(ip, other_nil_value); |
1765 __ cmp(reg, ip); | 1785 __ cmp(reg, ip); |
1766 __ b(eq, true_label); | 1786 __ b(eq, true_label); |
1767 __ JumpIfSmi(reg, false_label); | 1787 __ JumpIfSmi(reg, false_label); |
1768 // Check for undetectable objects by looking in the bit field in | 1788 // Check for undetectable objects by looking in the bit field in |
1769 // the map. The object has already been smi checked. | 1789 // the map. The object has already been smi checked. |
1770 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1790 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
1771 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); | 1791 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); |
1772 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); | 1792 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); |
1773 EmitBranch(true_block, false_block, ne); | 1793 EmitBranch(true_block, false_block, ne); |
1774 } | 1794 } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1911 // the temp registers, but not the input. Only input and temp2 may alias. | 1931 // the temp registers, but not the input. Only input and temp2 may alias. |
1912 void LCodeGen::EmitClassOfTest(Label* is_true, | 1932 void LCodeGen::EmitClassOfTest(Label* is_true, |
1913 Label* is_false, | 1933 Label* is_false, |
1914 Handle<String>class_name, | 1934 Handle<String>class_name, |
1915 Register input, | 1935 Register input, |
1916 Register temp, | 1936 Register temp, |
1917 Register temp2) { | 1937 Register temp2) { |
1918 ASSERT(!input.is(temp)); | 1938 ASSERT(!input.is(temp)); |
1919 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. | 1939 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. |
1920 __ JumpIfSmi(input, is_false); | 1940 __ JumpIfSmi(input, is_false); |
1921 __ CompareObjectType(input, temp, temp2, FIRST_SPEC_OBJECT_TYPE); | |
1922 __ b(lt, is_false); | |
1923 | 1941 |
1924 // Map is now in temp. | |
1925 // Functions have class 'Function'. | |
1926 __ CompareInstanceType(temp, temp2, FIRST_CALLABLE_SPEC_OBJECT_TYPE); | |
1927 if (class_name->IsEqualTo(CStrVector("Function"))) { | 1942 if (class_name->IsEqualTo(CStrVector("Function"))) { |
1928 __ b(ge, is_true); | 1943 // Assuming the following assertions, we can use the same compares to test |
| 1944 // for both being a function type and being in the object type range. |
| 1945 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
| 1946 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == |
| 1947 FIRST_SPEC_OBJECT_TYPE + 1); |
| 1948 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == |
| 1949 LAST_SPEC_OBJECT_TYPE - 1); |
| 1950 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
| 1951 __ CompareObjectType(input, temp, temp2, FIRST_SPEC_OBJECT_TYPE); |
| 1952 __ b(lt, is_false); |
| 1953 __ b(eq, is_true); |
| 1954 __ cmp(temp2, Operand(LAST_SPEC_OBJECT_TYPE)); |
| 1955 __ b(eq, is_true); |
1929 } else { | 1956 } else { |
1930 __ b(ge, is_false); | 1957 // Faster code path to avoid two compares: subtract lower bound from the |
| 1958 // actual type and do a signed compare with the width of the type range. |
| 1959 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 1960 __ ldrb(temp2, FieldMemOperand(temp, Map::kInstanceTypeOffset)); |
| 1961 __ sub(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 1962 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - |
| 1963 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 1964 __ b(gt, is_false); |
1931 } | 1965 } |
1932 | 1966 |
| 1967 // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. |
1933 // Check if the constructor in the map is a function. | 1968 // Check if the constructor in the map is a function. |
1934 __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset)); | 1969 __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset)); |
1935 | 1970 |
1936 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type and | |
1937 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after | |
1938 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter. | |
1939 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); | |
1940 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE == | |
1941 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1); | |
1942 | |
1943 // Objects with a non-function constructor have class 'Object'. | 1971 // Objects with a non-function constructor have class 'Object'. |
1944 __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE); | 1972 __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE); |
1945 if (class_name->IsEqualTo(CStrVector("Object"))) { | 1973 if (class_name->IsEqualTo(CStrVector("Object"))) { |
1946 __ b(ne, is_true); | 1974 __ b(ne, is_true); |
1947 } else { | 1975 } else { |
1948 __ b(ne, is_false); | 1976 __ b(ne, is_false); |
1949 } | 1977 } |
1950 | 1978 |
1951 // temp now contains the constructor function. Grab the | 1979 // temp now contains the constructor function. Grab the |
1952 // instance class name from there. | 1980 // instance class name from there. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2009 | 2037 |
2010 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2038 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
2011 class DeferredInstanceOfKnownGlobal: public LDeferredCode { | 2039 class DeferredInstanceOfKnownGlobal: public LDeferredCode { |
2012 public: | 2040 public: |
2013 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, | 2041 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
2014 LInstanceOfKnownGlobal* instr) | 2042 LInstanceOfKnownGlobal* instr) |
2015 : LDeferredCode(codegen), instr_(instr) { } | 2043 : LDeferredCode(codegen), instr_(instr) { } |
2016 virtual void Generate() { | 2044 virtual void Generate() { |
2017 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); | 2045 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); |
2018 } | 2046 } |
2019 | 2047 virtual LInstruction* instr() { return instr_; } |
2020 Label* map_check() { return &map_check_; } | 2048 Label* map_check() { return &map_check_; } |
2021 | |
2022 private: | 2049 private: |
2023 LInstanceOfKnownGlobal* instr_; | 2050 LInstanceOfKnownGlobal* instr_; |
2024 Label map_check_; | 2051 Label map_check_; |
2025 }; | 2052 }; |
2026 | 2053 |
2027 DeferredInstanceOfKnownGlobal* deferred; | 2054 DeferredInstanceOfKnownGlobal* deferred; |
2028 deferred = new DeferredInstanceOfKnownGlobal(this, instr); | 2055 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
2029 | 2056 |
2030 Label done, false_result; | 2057 Label done, false_result; |
2031 Register object = ToRegister(instr->InputAt(0)); | 2058 Register object = ToRegister(instr->InputAt(0)); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2173 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 2200 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
2174 __ add(sp, sp, Operand(sp_delta)); | 2201 __ add(sp, sp, Operand(sp_delta)); |
2175 __ Jump(lr); | 2202 __ Jump(lr); |
2176 } | 2203 } |
2177 | 2204 |
2178 | 2205 |
2179 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2206 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
2180 Register result = ToRegister(instr->result()); | 2207 Register result = ToRegister(instr->result()); |
2181 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); | 2208 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); |
2182 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); | 2209 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); |
2183 if (instr->hydrogen()->check_hole_value()) { | 2210 if (instr->hydrogen()->RequiresHoleCheck()) { |
2184 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2211 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
2185 __ cmp(result, ip); | 2212 __ cmp(result, ip); |
2186 DeoptimizeIf(eq, instr->environment()); | 2213 DeoptimizeIf(eq, instr->environment()); |
2187 } | 2214 } |
2188 } | 2215 } |
2189 | 2216 |
2190 | 2217 |
2191 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 2218 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
2192 ASSERT(ToRegister(instr->global_object()).is(r0)); | 2219 ASSERT(ToRegister(instr->global_object()).is(r0)); |
2193 ASSERT(ToRegister(instr->result()).is(r0)); | 2220 ASSERT(ToRegister(instr->result()).is(r0)); |
2194 | 2221 |
2195 __ mov(r2, Operand(instr->name())); | 2222 __ mov(r2, Operand(instr->name())); |
2196 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET | 2223 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET |
2197 : RelocInfo::CODE_TARGET_CONTEXT; | 2224 : RelocInfo::CODE_TARGET_CONTEXT; |
2198 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2225 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2199 CallCode(ic, mode, instr); | 2226 CallCode(ic, mode, instr); |
2200 } | 2227 } |
2201 | 2228 |
2202 | 2229 |
2203 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2230 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
2204 Register value = ToRegister(instr->InputAt(0)); | 2231 Register value = ToRegister(instr->InputAt(0)); |
2205 Register scratch = scratch0(); | 2232 Register scratch = scratch0(); |
| 2233 Register scratch2 = ToRegister(instr->TempAt(0)); |
2206 | 2234 |
2207 // Load the cell. | 2235 // Load the cell. |
2208 __ mov(scratch, Operand(Handle<Object>(instr->hydrogen()->cell()))); | 2236 __ mov(scratch, Operand(Handle<Object>(instr->hydrogen()->cell()))); |
2209 | 2237 |
2210 // If the cell we are storing to contains the hole it could have | 2238 // If the cell we are storing to contains the hole it could have |
2211 // been deleted from the property dictionary. In that case, we need | 2239 // been deleted from the property dictionary. In that case, we need |
2212 // to update the property details in the property dictionary to mark | 2240 // to update the property details in the property dictionary to mark |
2213 // it as no longer deleted. | 2241 // it as no longer deleted. |
2214 if (instr->hydrogen()->check_hole_value()) { | 2242 if (instr->hydrogen()->RequiresHoleCheck()) { |
2215 Register scratch2 = ToRegister(instr->TempAt(0)); | |
2216 __ ldr(scratch2, | 2243 __ ldr(scratch2, |
2217 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | 2244 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
2218 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2245 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
2219 __ cmp(scratch2, ip); | 2246 __ cmp(scratch2, ip); |
2220 DeoptimizeIf(eq, instr->environment()); | 2247 DeoptimizeIf(eq, instr->environment()); |
2221 } | 2248 } |
2222 | 2249 |
2223 // Store the value. | 2250 // Store the value. |
2224 __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | 2251 __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
| 2252 |
| 2253 // Cells are always in the remembered set. |
| 2254 __ RecordWriteField(scratch, |
| 2255 JSGlobalPropertyCell::kValueOffset, |
| 2256 value, |
| 2257 scratch2, |
| 2258 kLRHasBeenSaved, |
| 2259 kSaveFPRegs, |
| 2260 OMIT_REMEMBERED_SET); |
2225 } | 2261 } |
2226 | 2262 |
2227 | 2263 |
2228 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 2264 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
2229 ASSERT(ToRegister(instr->global_object()).is(r1)); | 2265 ASSERT(ToRegister(instr->global_object()).is(r1)); |
2230 ASSERT(ToRegister(instr->value()).is(r0)); | 2266 ASSERT(ToRegister(instr->value()).is(r0)); |
2231 | 2267 |
2232 __ mov(r2, Operand(instr->name())); | 2268 __ mov(r2, Operand(instr->name())); |
2233 Handle<Code> ic = instr->strict_mode() | 2269 Handle<Code> ic = instr->strict_mode() |
2234 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2270 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
2235 : isolate()->builtins()->StoreIC_Initialize(); | 2271 : isolate()->builtins()->StoreIC_Initialize(); |
2236 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 2272 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
2237 } | 2273 } |
2238 | 2274 |
2239 | 2275 |
2240 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2276 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
2241 Register context = ToRegister(instr->context()); | 2277 Register context = ToRegister(instr->context()); |
2242 Register result = ToRegister(instr->result()); | 2278 Register result = ToRegister(instr->result()); |
2243 __ ldr(result, ContextOperand(context, instr->slot_index())); | 2279 __ ldr(result, ContextOperand(context, instr->slot_index())); |
2244 } | 2280 } |
2245 | 2281 |
2246 | 2282 |
2247 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2283 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
2248 Register context = ToRegister(instr->context()); | 2284 Register context = ToRegister(instr->context()); |
2249 Register value = ToRegister(instr->value()); | 2285 Register value = ToRegister(instr->value()); |
2250 __ str(value, ContextOperand(context, instr->slot_index())); | 2286 MemOperand target = ContextOperand(context, instr->slot_index()); |
| 2287 __ str(value, target); |
2251 if (instr->needs_write_barrier()) { | 2288 if (instr->needs_write_barrier()) { |
2252 int offset = Context::SlotOffset(instr->slot_index()); | 2289 __ RecordWriteContextSlot(context, |
2253 __ RecordWrite(context, Operand(offset), value, scratch0()); | 2290 target.offset(), |
| 2291 value, |
| 2292 scratch0(), |
| 2293 kLRHasBeenSaved, |
| 2294 kSaveFPRegs); |
2254 } | 2295 } |
2255 } | 2296 } |
2256 | 2297 |
2257 | 2298 |
2258 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2299 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
2259 Register object = ToRegister(instr->InputAt(0)); | 2300 Register object = ToRegister(instr->InputAt(0)); |
2260 Register result = ToRegister(instr->result()); | 2301 Register result = ToRegister(instr->result()); |
2261 if (instr->hydrogen()->is_in_object()) { | 2302 if (instr->hydrogen()->is_in_object()) { |
2262 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); | 2303 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); |
2263 } else { | 2304 } else { |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2493 Operand operand = key_is_constant | 2534 Operand operand = key_is_constant |
2494 ? Operand(constant_key * (1 << shift_size) + | 2535 ? Operand(constant_key * (1 << shift_size) + |
2495 FixedDoubleArray::kHeaderSize - kHeapObjectTag) | 2536 FixedDoubleArray::kHeaderSize - kHeapObjectTag) |
2496 : Operand(key, LSL, shift_size); | 2537 : Operand(key, LSL, shift_size); |
2497 __ add(elements, elements, operand); | 2538 __ add(elements, elements, operand); |
2498 if (!key_is_constant) { | 2539 if (!key_is_constant) { |
2499 __ add(elements, elements, | 2540 __ add(elements, elements, |
2500 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); | 2541 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
2501 } | 2542 } |
2502 | 2543 |
2503 if (instr->hydrogen()->RequiresHoleCheck()) { | 2544 __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); |
2504 // TODO(danno): If no hole check is required, there is no need to allocate | 2545 __ cmp(scratch, Operand(kHoleNanUpper32)); |
2505 // elements into a temporary register, instead scratch can be used. | 2546 DeoptimizeIf(eq, instr->environment()); |
2506 __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); | |
2507 __ cmp(scratch, Operand(kHoleNanUpper32)); | |
2508 DeoptimizeIf(eq, instr->environment()); | |
2509 } | |
2510 | 2547 |
2511 __ vldr(result, elements, 0); | 2548 __ vldr(result, elements, 0); |
2512 } | 2549 } |
2513 | 2550 |
2514 | 2551 |
2515 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | 2552 void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
2516 LLoadKeyedSpecializedArrayElement* instr) { | 2553 LLoadKeyedSpecializedArrayElement* instr) { |
2517 Register external_pointer = ToRegister(instr->external_pointer()); | 2554 Register external_pointer = ToRegister(instr->external_pointer()); |
2518 Register key = no_reg; | 2555 Register key = no_reg; |
2519 ElementsKind elements_kind = instr->elements_kind(); | 2556 ElementsKind elements_kind = instr->elements_kind(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2570 __ cmp(result, Operand(0x80000000)); | 2607 __ cmp(result, Operand(0x80000000)); |
2571 // TODO(danno): we could be more clever here, perhaps having a special | 2608 // TODO(danno): we could be more clever here, perhaps having a special |
2572 // version of the stub that detects if the overflow case actually | 2609 // version of the stub that detects if the overflow case actually |
2573 // happens, and generate code that returns a double rather than int. | 2610 // happens, and generate code that returns a double rather than int. |
2574 DeoptimizeIf(cs, instr->environment()); | 2611 DeoptimizeIf(cs, instr->environment()); |
2575 break; | 2612 break; |
2576 case EXTERNAL_FLOAT_ELEMENTS: | 2613 case EXTERNAL_FLOAT_ELEMENTS: |
2577 case EXTERNAL_DOUBLE_ELEMENTS: | 2614 case EXTERNAL_DOUBLE_ELEMENTS: |
2578 case FAST_DOUBLE_ELEMENTS: | 2615 case FAST_DOUBLE_ELEMENTS: |
2579 case FAST_ELEMENTS: | 2616 case FAST_ELEMENTS: |
| 2617 case FAST_SMI_ONLY_ELEMENTS: |
2580 case DICTIONARY_ELEMENTS: | 2618 case DICTIONARY_ELEMENTS: |
2581 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2619 case NON_STRICT_ARGUMENTS_ELEMENTS: |
2582 UNREACHABLE(); | 2620 UNREACHABLE(); |
2583 break; | 2621 break; |
2584 } | 2622 } |
2585 } | 2623 } |
2586 } | 2624 } |
2587 | 2625 |
2588 | 2626 |
2589 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2627 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2899 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2937 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
2900 // Class for deferred case. | 2938 // Class for deferred case. |
2901 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 2939 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
2902 public: | 2940 public: |
2903 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2941 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
2904 LUnaryMathOperation* instr) | 2942 LUnaryMathOperation* instr) |
2905 : LDeferredCode(codegen), instr_(instr) { } | 2943 : LDeferredCode(codegen), instr_(instr) { } |
2906 virtual void Generate() { | 2944 virtual void Generate() { |
2907 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 2945 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
2908 } | 2946 } |
| 2947 virtual LInstruction* instr() { return instr_; } |
2909 private: | 2948 private: |
2910 LUnaryMathOperation* instr_; | 2949 LUnaryMathOperation* instr_; |
2911 }; | 2950 }; |
2912 | 2951 |
2913 Representation r = instr->hydrogen()->value()->representation(); | 2952 Representation r = instr->hydrogen()->value()->representation(); |
2914 if (r.IsDouble()) { | 2953 if (r.IsDouble()) { |
2915 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); | 2954 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); |
2916 DwVfpRegister result = ToDoubleRegister(instr->result()); | 2955 DwVfpRegister result = ToDoubleRegister(instr->result()); |
2917 __ vabs(result, input); | 2956 __ vabs(result, input); |
2918 } else if (r.IsInteger32()) { | 2957 } else if (r.IsInteger32()) { |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3195 CallCode(ic, mode, instr); | 3234 CallCode(ic, mode, instr); |
3196 // Restore context register. | 3235 // Restore context register. |
3197 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3236 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3198 } | 3237 } |
3199 | 3238 |
3200 | 3239 |
3201 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3240 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
3202 ASSERT(ToRegister(instr->result()).is(r0)); | 3241 ASSERT(ToRegister(instr->result()).is(r0)); |
3203 | 3242 |
3204 int arity = instr->arity(); | 3243 int arity = instr->arity(); |
3205 CallFunctionStub stub(arity, RECEIVER_MIGHT_BE_IMPLICIT); | 3244 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
3206 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 3245 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
3207 __ Drop(1); | 3246 __ Drop(1); |
3208 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3247 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3209 } | 3248 } |
3210 | 3249 |
3211 | 3250 |
3212 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 3251 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
3213 ASSERT(ToRegister(instr->result()).is(r0)); | 3252 ASSERT(ToRegister(instr->result()).is(r0)); |
3214 | 3253 |
3215 int arity = instr->arity(); | 3254 int arity = instr->arity(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3255 if (!instr->transition().is_null()) { | 3294 if (!instr->transition().is_null()) { |
3256 __ mov(scratch, Operand(instr->transition())); | 3295 __ mov(scratch, Operand(instr->transition())); |
3257 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3296 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
3258 } | 3297 } |
3259 | 3298 |
3260 // Do the store. | 3299 // Do the store. |
3261 if (instr->is_in_object()) { | 3300 if (instr->is_in_object()) { |
3262 __ str(value, FieldMemOperand(object, offset)); | 3301 __ str(value, FieldMemOperand(object, offset)); |
3263 if (instr->needs_write_barrier()) { | 3302 if (instr->needs_write_barrier()) { |
3264 // Update the write barrier for the object for in-object properties. | 3303 // Update the write barrier for the object for in-object properties. |
3265 __ RecordWrite(object, Operand(offset), value, scratch); | 3304 __ RecordWriteField( |
| 3305 object, offset, value, scratch, kLRHasBeenSaved, kSaveFPRegs); |
3266 } | 3306 } |
3267 } else { | 3307 } else { |
3268 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 3308 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
3269 __ str(value, FieldMemOperand(scratch, offset)); | 3309 __ str(value, FieldMemOperand(scratch, offset)); |
3270 if (instr->needs_write_barrier()) { | 3310 if (instr->needs_write_barrier()) { |
3271 // Update the write barrier for the properties array. | 3311 // Update the write barrier for the properties array. |
3272 // object is used as a scratch register. | 3312 // object is used as a scratch register. |
3273 __ RecordWrite(scratch, Operand(offset), value, object); | 3313 __ RecordWriteField( |
| 3314 scratch, offset, value, object, kLRHasBeenSaved, kSaveFPRegs); |
3274 } | 3315 } |
3275 } | 3316 } |
3276 } | 3317 } |
3277 | 3318 |
3278 | 3319 |
3279 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 3320 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
3280 ASSERT(ToRegister(instr->object()).is(r1)); | 3321 ASSERT(ToRegister(instr->object()).is(r1)); |
3281 ASSERT(ToRegister(instr->value()).is(r0)); | 3322 ASSERT(ToRegister(instr->value()).is(r0)); |
3282 | 3323 |
3283 // Name is always in r2. | 3324 // Name is always in r2. |
(...skipping 10 matching lines...) Expand all Loading... |
3294 DeoptimizeIf(hs, instr->environment()); | 3335 DeoptimizeIf(hs, instr->environment()); |
3295 } | 3336 } |
3296 | 3337 |
3297 | 3338 |
3298 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 3339 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
3299 Register value = ToRegister(instr->value()); | 3340 Register value = ToRegister(instr->value()); |
3300 Register elements = ToRegister(instr->object()); | 3341 Register elements = ToRegister(instr->object()); |
3301 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; | 3342 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; |
3302 Register scratch = scratch0(); | 3343 Register scratch = scratch0(); |
3303 | 3344 |
| 3345 // This instruction cannot handle the FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS |
| 3346 // conversion, so it deopts in that case. |
| 3347 if (instr->hydrogen()->ValueNeedsSmiCheck()) { |
| 3348 __ tst(value, Operand(kSmiTagMask)); |
| 3349 DeoptimizeIf(ne, instr->environment()); |
| 3350 } |
| 3351 |
3304 // Do the store. | 3352 // Do the store. |
3305 if (instr->key()->IsConstantOperand()) { | 3353 if (instr->key()->IsConstantOperand()) { |
3306 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 3354 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
3307 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | 3355 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
3308 int offset = | 3356 int offset = |
3309 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; | 3357 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; |
3310 __ str(value, FieldMemOperand(elements, offset)); | 3358 __ str(value, FieldMemOperand(elements, offset)); |
3311 } else { | 3359 } else { |
3312 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); | 3360 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
3313 __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 3361 __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize)); |
3314 } | 3362 } |
3315 | 3363 |
3316 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3364 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3317 // Compute address of modified element and store it into key register. | 3365 // Compute address of modified element and store it into key register. |
3318 __ add(key, scratch, Operand(FixedArray::kHeaderSize)); | 3366 __ add(key, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
3319 __ RecordWrite(elements, key, value); | 3367 __ RecordWrite(elements, key, value, kLRHasBeenSaved, kSaveFPRegs); |
3320 } | 3368 } |
3321 } | 3369 } |
3322 | 3370 |
3323 | 3371 |
3324 void LCodeGen::DoStoreKeyedFastDoubleElement( | 3372 void LCodeGen::DoStoreKeyedFastDoubleElement( |
3325 LStoreKeyedFastDoubleElement* instr) { | 3373 LStoreKeyedFastDoubleElement* instr) { |
3326 DwVfpRegister value = ToDoubleRegister(instr->value()); | 3374 DwVfpRegister value = ToDoubleRegister(instr->value()); |
3327 Register elements = ToRegister(instr->elements()); | 3375 Register elements = ToRegister(instr->elements()); |
3328 Register key = no_reg; | 3376 Register key = no_reg; |
3329 Register scratch = scratch0(); | 3377 Register scratch = scratch0(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3410 __ strh(value, mem_operand); | 3458 __ strh(value, mem_operand); |
3411 break; | 3459 break; |
3412 case EXTERNAL_INT_ELEMENTS: | 3460 case EXTERNAL_INT_ELEMENTS: |
3413 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3461 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3414 __ str(value, mem_operand); | 3462 __ str(value, mem_operand); |
3415 break; | 3463 break; |
3416 case EXTERNAL_FLOAT_ELEMENTS: | 3464 case EXTERNAL_FLOAT_ELEMENTS: |
3417 case EXTERNAL_DOUBLE_ELEMENTS: | 3465 case EXTERNAL_DOUBLE_ELEMENTS: |
3418 case FAST_DOUBLE_ELEMENTS: | 3466 case FAST_DOUBLE_ELEMENTS: |
3419 case FAST_ELEMENTS: | 3467 case FAST_ELEMENTS: |
| 3468 case FAST_SMI_ONLY_ELEMENTS: |
3420 case DICTIONARY_ELEMENTS: | 3469 case DICTIONARY_ELEMENTS: |
3421 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3470 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3422 UNREACHABLE(); | 3471 UNREACHABLE(); |
3423 break; | 3472 break; |
3424 } | 3473 } |
3425 } | 3474 } |
3426 } | 3475 } |
3427 | 3476 |
3428 | 3477 |
3429 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3478 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
(...skipping 15 matching lines...) Expand all Loading... |
3445 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 3494 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
3446 } | 3495 } |
3447 | 3496 |
3448 | 3497 |
3449 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 3498 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
3450 class DeferredStringCharCodeAt: public LDeferredCode { | 3499 class DeferredStringCharCodeAt: public LDeferredCode { |
3451 public: | 3500 public: |
3452 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 3501 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
3453 : LDeferredCode(codegen), instr_(instr) { } | 3502 : LDeferredCode(codegen), instr_(instr) { } |
3454 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 3503 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } |
| 3504 virtual LInstruction* instr() { return instr_; } |
3455 private: | 3505 private: |
3456 LStringCharCodeAt* instr_; | 3506 LStringCharCodeAt* instr_; |
3457 }; | 3507 }; |
3458 | 3508 |
3459 Register string = ToRegister(instr->string()); | 3509 Register string = ToRegister(instr->string()); |
3460 Register index = ToRegister(instr->index()); | 3510 Register index = ToRegister(instr->index()); |
3461 Register result = ToRegister(instr->result()); | 3511 Register result = ToRegister(instr->result()); |
3462 | 3512 |
3463 DeferredStringCharCodeAt* deferred = | 3513 DeferredStringCharCodeAt* deferred = |
3464 new DeferredStringCharCodeAt(this, instr); | 3514 new DeferredStringCharCodeAt(this, instr); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3568 __ StoreToSafepointRegisterSlot(r0, result); | 3618 __ StoreToSafepointRegisterSlot(r0, result); |
3569 } | 3619 } |
3570 | 3620 |
3571 | 3621 |
3572 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 3622 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
3573 class DeferredStringCharFromCode: public LDeferredCode { | 3623 class DeferredStringCharFromCode: public LDeferredCode { |
3574 public: | 3624 public: |
3575 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 3625 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
3576 : LDeferredCode(codegen), instr_(instr) { } | 3626 : LDeferredCode(codegen), instr_(instr) { } |
3577 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } | 3627 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } |
| 3628 virtual LInstruction* instr() { return instr_; } |
3578 private: | 3629 private: |
3579 LStringCharFromCode* instr_; | 3630 LStringCharFromCode* instr_; |
3580 }; | 3631 }; |
3581 | 3632 |
3582 DeferredStringCharFromCode* deferred = | 3633 DeferredStringCharFromCode* deferred = |
3583 new DeferredStringCharFromCode(this, instr); | 3634 new DeferredStringCharFromCode(this, instr); |
3584 | 3635 |
3585 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 3636 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
3586 Register char_code = ToRegister(instr->char_code()); | 3637 Register char_code = ToRegister(instr->char_code()); |
3587 Register result = ToRegister(instr->result()); | 3638 Register result = ToRegister(instr->result()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3639 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); | 3690 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); |
3640 } | 3691 } |
3641 | 3692 |
3642 | 3693 |
3643 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 3694 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
3644 class DeferredNumberTagI: public LDeferredCode { | 3695 class DeferredNumberTagI: public LDeferredCode { |
3645 public: | 3696 public: |
3646 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 3697 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
3647 : LDeferredCode(codegen), instr_(instr) { } | 3698 : LDeferredCode(codegen), instr_(instr) { } |
3648 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } | 3699 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } |
| 3700 virtual LInstruction* instr() { return instr_; } |
3649 private: | 3701 private: |
3650 LNumberTagI* instr_; | 3702 LNumberTagI* instr_; |
3651 }; | 3703 }; |
3652 | 3704 |
3653 LOperand* input = instr->InputAt(0); | 3705 LOperand* input = instr->InputAt(0); |
3654 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3706 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
3655 Register reg = ToRegister(input); | 3707 Register reg = ToRegister(input); |
3656 | 3708 |
3657 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); | 3709 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); |
3658 __ SmiTag(reg, SetCC); | 3710 __ SmiTag(reg, SetCC); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3704 __ StoreToSafepointRegisterSlot(reg, reg); | 3756 __ StoreToSafepointRegisterSlot(reg, reg); |
3705 } | 3757 } |
3706 | 3758 |
3707 | 3759 |
3708 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 3760 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
3709 class DeferredNumberTagD: public LDeferredCode { | 3761 class DeferredNumberTagD: public LDeferredCode { |
3710 public: | 3762 public: |
3711 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 3763 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
3712 : LDeferredCode(codegen), instr_(instr) { } | 3764 : LDeferredCode(codegen), instr_(instr) { } |
3713 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 3765 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 3766 virtual LInstruction* instr() { return instr_; } |
3714 private: | 3767 private: |
3715 LNumberTagD* instr_; | 3768 LNumberTagD* instr_; |
3716 }; | 3769 }; |
3717 | 3770 |
3718 DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 3771 DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
3719 Register scratch = scratch0(); | 3772 Register scratch = scratch0(); |
3720 Register reg = ToRegister(instr->result()); | 3773 Register reg = ToRegister(instr->result()); |
3721 Register temp1 = ToRegister(instr->TempAt(0)); | 3774 Register temp1 = ToRegister(instr->TempAt(0)); |
3722 Register temp2 = ToRegister(instr->TempAt(1)); | 3775 Register temp2 = ToRegister(instr->TempAt(1)); |
3723 | 3776 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3812 // Smi to double register conversion | 3865 // Smi to double register conversion |
3813 __ bind(&load_smi); | 3866 __ bind(&load_smi); |
3814 __ SmiUntag(input_reg); // Untag smi before converting to float. | 3867 __ SmiUntag(input_reg); // Untag smi before converting to float. |
3815 __ vmov(flt_scratch, input_reg); | 3868 __ vmov(flt_scratch, input_reg); |
3816 __ vcvt_f64_s32(result_reg, flt_scratch); | 3869 __ vcvt_f64_s32(result_reg, flt_scratch); |
3817 __ SmiTag(input_reg); // Retag smi. | 3870 __ SmiTag(input_reg); // Retag smi. |
3818 __ bind(&done); | 3871 __ bind(&done); |
3819 } | 3872 } |
3820 | 3873 |
3821 | 3874 |
3822 class DeferredTaggedToI: public LDeferredCode { | |
3823 public: | |
3824 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | |
3825 : LDeferredCode(codegen), instr_(instr) { } | |
3826 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | |
3827 private: | |
3828 LTaggedToI* instr_; | |
3829 }; | |
3830 | |
3831 | |
3832 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3875 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
3833 Register input_reg = ToRegister(instr->InputAt(0)); | 3876 Register input_reg = ToRegister(instr->InputAt(0)); |
3834 Register scratch1 = scratch0(); | 3877 Register scratch1 = scratch0(); |
3835 Register scratch2 = ToRegister(instr->TempAt(0)); | 3878 Register scratch2 = ToRegister(instr->TempAt(0)); |
3836 DwVfpRegister double_scratch = double_scratch0(); | 3879 DwVfpRegister double_scratch = double_scratch0(); |
3837 SwVfpRegister single_scratch = double_scratch.low(); | 3880 SwVfpRegister single_scratch = double_scratch.low(); |
3838 | 3881 |
3839 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); | 3882 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); |
3840 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); | 3883 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); |
3841 | 3884 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3904 __ vmov(scratch1, double_scratch.high()); | 3947 __ vmov(scratch1, double_scratch.high()); |
3905 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 3948 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
3906 DeoptimizeIf(ne, instr->environment()); | 3949 DeoptimizeIf(ne, instr->environment()); |
3907 } | 3950 } |
3908 } | 3951 } |
3909 __ bind(&done); | 3952 __ bind(&done); |
3910 } | 3953 } |
3911 | 3954 |
3912 | 3955 |
3913 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 3956 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 3957 class DeferredTaggedToI: public LDeferredCode { |
| 3958 public: |
| 3959 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 3960 : LDeferredCode(codegen), instr_(instr) { } |
| 3961 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 3962 virtual LInstruction* instr() { return instr_; } |
| 3963 private: |
| 3964 LTaggedToI* instr_; |
| 3965 }; |
| 3966 |
3914 LOperand* input = instr->InputAt(0); | 3967 LOperand* input = instr->InputAt(0); |
3915 ASSERT(input->IsRegister()); | 3968 ASSERT(input->IsRegister()); |
3916 ASSERT(input->Equals(instr->result())); | 3969 ASSERT(input->Equals(instr->result())); |
3917 | 3970 |
3918 Register input_reg = ToRegister(input); | 3971 Register input_reg = ToRegister(input); |
3919 | 3972 |
3920 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); | 3973 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); |
3921 | 3974 |
3922 // Optimistically untag the input. | 3975 // Optimistically untag the input. |
3923 // If the input is a HeapObject, SmiUntag will set the carry flag. | 3976 // If the input is a HeapObject, SmiUntag will set the carry flag. |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4336 __ CompareRoot(input, Heap::kUndefinedValueRootIndex); | 4389 __ CompareRoot(input, Heap::kUndefinedValueRootIndex); |
4337 __ b(eq, true_label); | 4390 __ b(eq, true_label); |
4338 __ JumpIfSmi(input, false_label); | 4391 __ JumpIfSmi(input, false_label); |
4339 // Check for undetectable objects => true. | 4392 // Check for undetectable objects => true. |
4340 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); | 4393 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
4341 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); | 4394 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); |
4342 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 4395 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
4343 final_branch_condition = ne; | 4396 final_branch_condition = ne; |
4344 | 4397 |
4345 } else if (type_name->Equals(heap()->function_symbol())) { | 4398 } else if (type_name->Equals(heap()->function_symbol())) { |
| 4399 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
4346 __ JumpIfSmi(input, false_label); | 4400 __ JumpIfSmi(input, false_label); |
4347 __ CompareObjectType(input, input, scratch, | 4401 __ CompareObjectType(input, scratch, input, JS_FUNCTION_TYPE); |
4348 FIRST_CALLABLE_SPEC_OBJECT_TYPE); | 4402 __ b(eq, true_label); |
4349 final_branch_condition = ge; | 4403 __ cmp(input, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 4404 final_branch_condition = eq; |
4350 | 4405 |
4351 } else if (type_name->Equals(heap()->object_symbol())) { | 4406 } else if (type_name->Equals(heap()->object_symbol())) { |
4352 __ JumpIfSmi(input, false_label); | 4407 __ JumpIfSmi(input, false_label); |
4353 if (!FLAG_harmony_typeof) { | 4408 if (!FLAG_harmony_typeof) { |
4354 __ CompareRoot(input, Heap::kNullValueRootIndex); | 4409 __ CompareRoot(input, Heap::kNullValueRootIndex); |
4355 __ b(eq, true_label); | 4410 __ b(eq, true_label); |
4356 } | 4411 } |
4357 __ CompareObjectType(input, input, scratch, | 4412 __ CompareObjectType(input, input, scratch, |
4358 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4413 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); |
4359 __ b(lt, false_label); | 4414 __ b(lt, false_label); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4461 safepoints_.SetPcAfterGap(pc); | 4516 safepoints_.SetPcAfterGap(pc); |
4462 } | 4517 } |
4463 | 4518 |
4464 | 4519 |
4465 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 4520 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
4466 class DeferredStackCheck: public LDeferredCode { | 4521 class DeferredStackCheck: public LDeferredCode { |
4467 public: | 4522 public: |
4468 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) | 4523 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
4469 : LDeferredCode(codegen), instr_(instr) { } | 4524 : LDeferredCode(codegen), instr_(instr) { } |
4470 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 4525 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } |
| 4526 virtual LInstruction* instr() { return instr_; } |
4471 private: | 4527 private: |
4472 LStackCheck* instr_; | 4528 LStackCheck* instr_; |
4473 }; | 4529 }; |
4474 | 4530 |
4475 if (instr->hydrogen()->is_function_entry()) { | 4531 if (instr->hydrogen()->is_function_entry()) { |
4476 // Perform stack overflow check. | 4532 // Perform stack overflow check. |
4477 Label done; | 4533 Label done; |
4478 __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 4534 __ LoadRoot(ip, Heap::kStackLimitRootIndex); |
4479 __ cmp(sp, Operand(ip)); | 4535 __ cmp(sp, Operand(ip)); |
4480 __ b(hs, &done); | 4536 __ b(hs, &done); |
(...skipping 29 matching lines...) Expand all Loading... |
4510 ASSERT(osr_pc_offset_ == -1); | 4566 ASSERT(osr_pc_offset_ == -1); |
4511 osr_pc_offset_ = masm()->pc_offset(); | 4567 osr_pc_offset_ = masm()->pc_offset(); |
4512 } | 4568 } |
4513 | 4569 |
4514 | 4570 |
4515 | 4571 |
4516 | 4572 |
4517 #undef __ | 4573 #undef __ |
4518 | 4574 |
4519 } } // namespace v8::internal | 4575 } } // namespace v8::internal |
OLD | NEW |