Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: src/arm/lithium-codegen-arm.cc

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698