OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 } | 550 } |
551 | 551 |
552 | 552 |
553 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { | 553 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { |
554 return value->IsConstant() | 554 return value->IsConstant() |
555 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 555 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
556 : UseRegisterAtStart(value); | 556 : UseRegisterAtStart(value); |
557 } | 557 } |
558 | 558 |
559 | 559 |
| 560 LOperand* LChunkBuilder::UseConstant(HValue* value) { |
| 561 return chunk_->DefineConstantOperand(HConstant::cast(value)); |
| 562 } |
| 563 |
| 564 |
560 LOperand* LChunkBuilder::UseAny(HValue* value) { | 565 LOperand* LChunkBuilder::UseAny(HValue* value) { |
561 return value->IsConstant() | 566 return value->IsConstant() |
562 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 567 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
563 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY)); | 568 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY)); |
564 } | 569 } |
565 | 570 |
566 | 571 |
567 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { | 572 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { |
568 if (value->EmitAtUses()) { | 573 if (value->EmitAtUses()) { |
569 HInstruction* instr = HInstruction::cast(value); | 574 HInstruction* instr = HInstruction::cast(value); |
(...skipping 1538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2108 | 2113 |
2109 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 2114 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
2110 LOperand* object = UseFixed(instr->object(), rdx); | 2115 LOperand* object = UseFixed(instr->object(), rdx); |
2111 LOperand* key = UseFixed(instr->key(), rax); | 2116 LOperand* key = UseFixed(instr->key(), rax); |
2112 | 2117 |
2113 LLoadKeyedGeneric* result = new(zone()) LLoadKeyedGeneric(object, key); | 2118 LLoadKeyedGeneric* result = new(zone()) LLoadKeyedGeneric(object, key); |
2114 return MarkAsCall(DefineFixed(result, rax), instr); | 2119 return MarkAsCall(DefineFixed(result, rax), instr); |
2115 } | 2120 } |
2116 | 2121 |
2117 | 2122 |
2118 // DoStoreKeyed and DoStoreNamedField have special considerations for allowing | |
2119 // use of a constant instead of a register. | |
2120 static bool StoreConstantValueAllowed(HValue* value) { | |
2121 if (value->IsConstant()) { | |
2122 HConstant* constant_value = HConstant::cast(value); | |
2123 return constant_value->HasSmiValue() | |
2124 || constant_value->HasDoubleValue() | |
2125 || constant_value->ImmortalImmovable(); | |
2126 } | |
2127 return false; | |
2128 } | |
2129 | |
2130 | |
2131 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { | 2123 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
2132 ElementsKind elements_kind = instr->elements_kind(); | 2124 ElementsKind elements_kind = instr->elements_kind(); |
2133 bool clobbers_key = instr->key()->representation().IsTagged(); | 2125 bool clobbers_key = instr->key()->representation().IsTagged(); |
2134 | 2126 |
2135 if (!instr->is_external()) { | 2127 if (!instr->is_external()) { |
2136 ASSERT(instr->elements()->representation().IsTagged()); | 2128 ASSERT(instr->elements()->representation().IsTagged()); |
2137 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 2129 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
2138 LOperand* object = NULL; | 2130 LOperand* object = NULL; |
2139 LOperand* key = NULL; | 2131 LOperand* key = NULL; |
2140 LOperand* val = NULL; | 2132 LOperand* val = NULL; |
2141 | 2133 |
2142 if (instr->value()->representation().IsDouble()) { | 2134 if (instr->value()->representation().IsDouble()) { |
2143 object = UseRegisterAtStart(instr->elements()); | 2135 object = UseRegisterAtStart(instr->elements()); |
2144 val = UseTempRegister(instr->value()); | 2136 val = UseTempRegister(instr->value()); |
2145 key = clobbers_key ? UseTempRegister(instr->key()) | 2137 key = clobbers_key ? UseTempRegister(instr->key()) |
2146 : UseRegisterOrConstantAtStart(instr->key()); | 2138 : UseRegisterOrConstantAtStart(instr->key()); |
2147 } else { | 2139 } else { |
2148 ASSERT(instr->value()->representation().IsTagged()); | 2140 ASSERT(instr->value()->representation().IsTagged()); |
2149 object = UseTempRegister(instr->elements()); | 2141 object = UseTempRegister(instr->elements()); |
2150 if (needs_write_barrier) { | 2142 if (needs_write_barrier) { |
2151 val = UseTempRegister(instr->value()); | 2143 val = UseTempRegister(instr->value()); |
2152 key = UseTempRegister(instr->key()); | 2144 key = UseTempRegister(instr->key()); |
2153 } else { | 2145 } else { |
2154 if (StoreConstantValueAllowed(instr->value())) { | 2146 val = UseRegisterOrConstantAtStart(instr->value()); |
2155 val = UseRegisterOrConstantAtStart(instr->value()); | |
2156 } else { | |
2157 val = UseRegisterAtStart(instr->value()); | |
2158 } | |
2159 | 2147 |
2160 if (clobbers_key) { | 2148 if (clobbers_key) { |
2161 key = UseTempRegister(instr->key()); | 2149 key = UseTempRegister(instr->key()); |
2162 } else if (StoreConstantValueAllowed(instr->key())) { | 2150 } else { |
2163 key = UseRegisterOrConstantAtStart(instr->key()); | 2151 key = UseRegisterOrConstantAtStart(instr->key()); |
2164 } else { | |
2165 key = UseRegisterAtStart(instr->key()); | |
2166 } | 2152 } |
2167 } | 2153 } |
2168 } | 2154 } |
2169 | 2155 |
2170 return new(zone()) LStoreKeyed(object, key, val); | 2156 return new(zone()) LStoreKeyed(object, key, val); |
2171 } | 2157 } |
2172 | 2158 |
2173 ASSERT( | 2159 ASSERT( |
2174 (instr->value()->representation().IsInteger32() && | 2160 (instr->value()->representation().IsInteger32() && |
2175 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && | 2161 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 if (needs_write_barrier) { | 2237 if (needs_write_barrier) { |
2252 obj = instr->is_in_object() | 2238 obj = instr->is_in_object() |
2253 ? UseRegister(instr->object()) | 2239 ? UseRegister(instr->object()) |
2254 : UseTempRegister(instr->object()); | 2240 : UseTempRegister(instr->object()); |
2255 } else { | 2241 } else { |
2256 obj = needs_write_barrier_for_map | 2242 obj = needs_write_barrier_for_map |
2257 ? UseRegister(instr->object()) | 2243 ? UseRegister(instr->object()) |
2258 : UseRegisterAtStart(instr->object()); | 2244 : UseRegisterAtStart(instr->object()); |
2259 } | 2245 } |
2260 | 2246 |
| 2247 bool can_be_constant = instr->value()->IsConstant() && |
| 2248 !HConstant::cast(instr->value())->InNewSpace(); |
| 2249 |
2261 LOperand* val; | 2250 LOperand* val; |
2262 if (needs_write_barrier) { | 2251 if (needs_write_barrier) { |
2263 val = UseTempRegister(instr->value()); | 2252 val = UseTempRegister(instr->value()); |
2264 } else if (StoreConstantValueAllowed(instr->value())) { | 2253 } else if (can_be_constant) { |
2265 val = UseRegisterOrConstant(instr->value()); | 2254 val = UseRegisterOrConstant(instr->value()); |
2266 } else { | 2255 } else { |
2267 val = UseRegister(instr->value()); | 2256 val = UseRegister(instr->value()); |
2268 } | 2257 } |
2269 | 2258 |
2270 // We only need a scratch register if we have a write barrier or we | 2259 // We only need a scratch register if we have a write barrier or we |
2271 // have a store into the properties array (not in-object-property). | 2260 // have a store into the properties array (not in-object-property). |
2272 LOperand* temp = (!instr->is_in_object() || needs_write_barrier || | 2261 LOperand* temp = (!instr->is_in_object() || needs_write_barrier || |
2273 needs_write_barrier_for_map) ? TempRegister() : NULL; | 2262 needs_write_barrier_for_map) ? TempRegister() : NULL; |
2274 | 2263 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2316 | 2305 |
2317 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) { | 2306 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) { |
2318 info()->MarkAsDeferredCalling(); | 2307 info()->MarkAsDeferredCalling(); |
2319 LAllocateObject* result = new(zone()) LAllocateObject(TempRegister()); | 2308 LAllocateObject* result = new(zone()) LAllocateObject(TempRegister()); |
2320 return AssignPointerMap(DefineAsRegister(result)); | 2309 return AssignPointerMap(DefineAsRegister(result)); |
2321 } | 2310 } |
2322 | 2311 |
2323 | 2312 |
2324 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { | 2313 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { |
2325 info()->MarkAsDeferredCalling(); | 2314 info()->MarkAsDeferredCalling(); |
2326 LOperand* size = UseTempRegister(instr->size()); | 2315 LOperand* size = instr->size()->IsConstant() |
| 2316 ? UseConstant(instr->size()) |
| 2317 : UseTempRegister(instr->size()); |
2327 LOperand* temp = TempRegister(); | 2318 LOperand* temp = TempRegister(); |
2328 LAllocate* result = new(zone()) LAllocate(size, temp); | 2319 LAllocate* result = new(zone()) LAllocate(size, temp); |
2329 return AssignPointerMap(DefineAsRegister(result)); | 2320 return AssignPointerMap(DefineAsRegister(result)); |
2330 } | 2321 } |
2331 | 2322 |
2332 | 2323 |
2333 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { | 2324 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { |
2334 return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, rax), instr); | 2325 return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, rax), instr); |
2335 } | 2326 } |
2336 | 2327 |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2562 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2553 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
2563 LOperand* object = UseRegister(instr->object()); | 2554 LOperand* object = UseRegister(instr->object()); |
2564 LOperand* index = UseTempRegister(instr->index()); | 2555 LOperand* index = UseTempRegister(instr->index()); |
2565 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); | 2556 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); |
2566 } | 2557 } |
2567 | 2558 |
2568 | 2559 |
2569 } } // namespace v8::internal | 2560 } } // namespace v8::internal |
2570 | 2561 |
2571 #endif // V8_TARGET_ARCH_X64 | 2562 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |