| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/crankshaft/ppc/lithium-ppc.h" | 5 #include "src/crankshaft/s390/lithium-s390.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/crankshaft/hydrogen-osr.h" | 9 #include "src/crankshaft/hydrogen-osr.h" |
| 10 #include "src/crankshaft/lithium-inl.h" | 10 #include "src/crankshaft/lithium-inl.h" |
| 11 #include "src/crankshaft/ppc/lithium-codegen-ppc.h" | 11 #include "src/crankshaft/s390/lithium-codegen-s390.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 | 15 |
| 16 #define DEFINE_COMPILE(type) \ | 16 #define DEFINE_COMPILE(type) \ |
| 17 void L##type::CompileToNative(LCodeGen* generator) { \ | 17 void L##type::CompileToNative(LCodeGen* generator) { \ |
| 18 generator->Do##type(this); \ | 18 generator->Do##type(this); \ |
| 19 } | 19 } |
| 20 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) | 20 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) |
| 21 #undef DEFINE_COMPILE | 21 #undef DEFINE_COMPILE |
| (...skipping 10 matching lines...) Expand all Loading... |
| 32 LUnallocated* operand = LUnallocated::cast(it.Current()); | 32 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 33 DCHECK(operand->HasFixedPolicy() || operand->IsUsedAtStart()); | 33 DCHECK(operand->HasFixedPolicy() || operand->IsUsedAtStart()); |
| 34 } | 34 } |
| 35 for (TempIterator it(this); !it.Done(); it.Advance()) { | 35 for (TempIterator it(this); !it.Done(); it.Advance()) { |
| 36 LUnallocated* operand = LUnallocated::cast(it.Current()); | 36 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 37 DCHECK(operand->HasFixedPolicy() || !operand->HasRegisterPolicy()); | 37 DCHECK(operand->HasFixedPolicy() || !operand->HasRegisterPolicy()); |
| 38 } | 38 } |
| 39 } | 39 } |
| 40 #endif | 40 #endif |
| 41 | 41 |
| 42 | |
| 43 void LInstruction::PrintTo(StringStream* stream) { | 42 void LInstruction::PrintTo(StringStream* stream) { |
| 44 stream->Add("%s ", this->Mnemonic()); | 43 stream->Add("%s ", this->Mnemonic()); |
| 45 | 44 |
| 46 PrintOutputOperandTo(stream); | 45 PrintOutputOperandTo(stream); |
| 47 | 46 |
| 48 PrintDataTo(stream); | 47 PrintDataTo(stream); |
| 49 | 48 |
| 50 if (HasEnvironment()) { | 49 if (HasEnvironment()) { |
| 51 stream->Add(" "); | 50 stream->Add(" "); |
| 52 environment()->PrintTo(stream); | 51 environment()->PrintTo(stream); |
| 53 } | 52 } |
| 54 | 53 |
| 55 if (HasPointerMap()) { | 54 if (HasPointerMap()) { |
| 56 stream->Add(" "); | 55 stream->Add(" "); |
| 57 pointer_map()->PrintTo(stream); | 56 pointer_map()->PrintTo(stream); |
| 58 } | 57 } |
| 59 } | 58 } |
| 60 | 59 |
| 61 | |
| 62 void LInstruction::PrintDataTo(StringStream* stream) { | 60 void LInstruction::PrintDataTo(StringStream* stream) { |
| 63 stream->Add("= "); | 61 stream->Add("= "); |
| 64 for (int i = 0; i < InputCount(); i++) { | 62 for (int i = 0; i < InputCount(); i++) { |
| 65 if (i > 0) stream->Add(" "); | 63 if (i > 0) stream->Add(" "); |
| 66 if (InputAt(i) == NULL) { | 64 if (InputAt(i) == NULL) { |
| 67 stream->Add("NULL"); | 65 stream->Add("NULL"); |
| 68 } else { | 66 } else { |
| 69 InputAt(i)->PrintTo(stream); | 67 InputAt(i)->PrintTo(stream); |
| 70 } | 68 } |
| 71 } | 69 } |
| 72 } | 70 } |
| 73 | 71 |
| 74 | |
| 75 void LInstruction::PrintOutputOperandTo(StringStream* stream) { | 72 void LInstruction::PrintOutputOperandTo(StringStream* stream) { |
| 76 if (HasResult()) result()->PrintTo(stream); | 73 if (HasResult()) result()->PrintTo(stream); |
| 77 } | 74 } |
| 78 | 75 |
| 79 | |
| 80 void LLabel::PrintDataTo(StringStream* stream) { | 76 void LLabel::PrintDataTo(StringStream* stream) { |
| 81 LGap::PrintDataTo(stream); | 77 LGap::PrintDataTo(stream); |
| 82 LLabel* rep = replacement(); | 78 LLabel* rep = replacement(); |
| 83 if (rep != NULL) { | 79 if (rep != NULL) { |
| 84 stream->Add(" Dead block replaced with B%d", rep->block_id()); | 80 stream->Add(" Dead block replaced with B%d", rep->block_id()); |
| 85 } | 81 } |
| 86 } | 82 } |
| 87 | 83 |
| 88 | |
| 89 bool LGap::IsRedundant() const { | 84 bool LGap::IsRedundant() const { |
| 90 for (int i = 0; i < 4; i++) { | 85 for (int i = 0; i < 4; i++) { |
| 91 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { | 86 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { |
| 92 return false; | 87 return false; |
| 93 } | 88 } |
| 94 } | 89 } |
| 95 | 90 |
| 96 return true; | 91 return true; |
| 97 } | 92 } |
| 98 | 93 |
| 99 | |
| 100 void LGap::PrintDataTo(StringStream* stream) { | 94 void LGap::PrintDataTo(StringStream* stream) { |
| 101 for (int i = 0; i < 4; i++) { | 95 for (int i = 0; i < 4; i++) { |
| 102 stream->Add("("); | 96 stream->Add("("); |
| 103 if (parallel_moves_[i] != NULL) { | 97 if (parallel_moves_[i] != NULL) { |
| 104 parallel_moves_[i]->PrintDataTo(stream); | 98 parallel_moves_[i]->PrintDataTo(stream); |
| 105 } | 99 } |
| 106 stream->Add(") "); | 100 stream->Add(") "); |
| 107 } | 101 } |
| 108 } | 102 } |
| 109 | 103 |
| 110 | |
| 111 const char* LArithmeticD::Mnemonic() const { | 104 const char* LArithmeticD::Mnemonic() const { |
| 112 switch (op()) { | 105 switch (op()) { |
| 113 case Token::ADD: | 106 case Token::ADD: |
| 114 return "add-d"; | 107 return "add-d"; |
| 115 case Token::SUB: | 108 case Token::SUB: |
| 116 return "sub-d"; | 109 return "sub-d"; |
| 117 case Token::MUL: | 110 case Token::MUL: |
| 118 return "mul-d"; | 111 return "mul-d"; |
| 119 case Token::DIV: | 112 case Token::DIV: |
| 120 return "div-d"; | 113 return "div-d"; |
| 121 case Token::MOD: | 114 case Token::MOD: |
| 122 return "mod-d"; | 115 return "mod-d"; |
| 123 default: | 116 default: |
| 124 UNREACHABLE(); | 117 UNREACHABLE(); |
| 125 return NULL; | 118 return NULL; |
| 126 } | 119 } |
| 127 } | 120 } |
| 128 | 121 |
| 129 | |
| 130 const char* LArithmeticT::Mnemonic() const { | 122 const char* LArithmeticT::Mnemonic() const { |
| 131 switch (op()) { | 123 switch (op()) { |
| 132 case Token::ADD: | 124 case Token::ADD: |
| 133 return "add-t"; | 125 return "add-t"; |
| 134 case Token::SUB: | 126 case Token::SUB: |
| 135 return "sub-t"; | 127 return "sub-t"; |
| 136 case Token::MUL: | 128 case Token::MUL: |
| 137 return "mul-t"; | 129 return "mul-t"; |
| 138 case Token::MOD: | 130 case Token::MOD: |
| 139 return "mod-t"; | 131 return "mod-t"; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 152 case Token::SAR: | 144 case Token::SAR: |
| 153 return "sar-t"; | 145 return "sar-t"; |
| 154 case Token::SHR: | 146 case Token::SHR: |
| 155 return "shr-t"; | 147 return "shr-t"; |
| 156 default: | 148 default: |
| 157 UNREACHABLE(); | 149 UNREACHABLE(); |
| 158 return NULL; | 150 return NULL; |
| 159 } | 151 } |
| 160 } | 152 } |
| 161 | 153 |
| 162 | |
| 163 bool LGoto::HasInterestingComment(LCodeGen* gen) const { | 154 bool LGoto::HasInterestingComment(LCodeGen* gen) const { |
| 164 return !gen->IsNextEmittedBlock(block_id()); | 155 return !gen->IsNextEmittedBlock(block_id()); |
| 165 } | 156 } |
| 166 | 157 |
| 167 | |
| 168 void LGoto::PrintDataTo(StringStream* stream) { | 158 void LGoto::PrintDataTo(StringStream* stream) { |
| 169 stream->Add("B%d", block_id()); | 159 stream->Add("B%d", block_id()); |
| 170 } | 160 } |
| 171 | 161 |
| 172 | |
| 173 void LBranch::PrintDataTo(StringStream* stream) { | 162 void LBranch::PrintDataTo(StringStream* stream) { |
| 174 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); | 163 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); |
| 175 value()->PrintTo(stream); | 164 value()->PrintTo(stream); |
| 176 } | 165 } |
| 177 | 166 |
| 178 | |
| 179 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) { | 167 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) { |
| 180 stream->Add("if "); | 168 stream->Add("if "); |
| 181 left()->PrintTo(stream); | 169 left()->PrintTo(stream); |
| 182 stream->Add(" %s ", Token::String(op())); | 170 stream->Add(" %s ", Token::String(op())); |
| 183 right()->PrintTo(stream); | 171 right()->PrintTo(stream); |
| 184 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); | 172 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); |
| 185 } | 173 } |
| 186 | 174 |
| 187 | |
| 188 void LIsStringAndBranch::PrintDataTo(StringStream* stream) { | 175 void LIsStringAndBranch::PrintDataTo(StringStream* stream) { |
| 189 stream->Add("if is_string("); | 176 stream->Add("if is_string("); |
| 190 value()->PrintTo(stream); | 177 value()->PrintTo(stream); |
| 191 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 178 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 192 } | 179 } |
| 193 | 180 |
| 194 | |
| 195 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { | 181 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { |
| 196 stream->Add("if is_smi("); | 182 stream->Add("if is_smi("); |
| 197 value()->PrintTo(stream); | 183 value()->PrintTo(stream); |
| 198 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 184 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 199 } | 185 } |
| 200 | 186 |
| 201 | |
| 202 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) { | 187 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) { |
| 203 stream->Add("if is_undetectable("); | 188 stream->Add("if is_undetectable("); |
| 204 value()->PrintTo(stream); | 189 value()->PrintTo(stream); |
| 205 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 190 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 206 } | 191 } |
| 207 | 192 |
| 208 | |
| 209 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) { | 193 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) { |
| 210 stream->Add("if string_compare("); | 194 stream->Add("if string_compare("); |
| 211 left()->PrintTo(stream); | 195 left()->PrintTo(stream); |
| 212 right()->PrintTo(stream); | 196 right()->PrintTo(stream); |
| 213 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 197 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 214 } | 198 } |
| 215 | 199 |
| 216 | |
| 217 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { | 200 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { |
| 218 stream->Add("if has_instance_type("); | 201 stream->Add("if has_instance_type("); |
| 219 value()->PrintTo(stream); | 202 value()->PrintTo(stream); |
| 220 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 203 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 221 } | 204 } |
| 222 | 205 |
| 223 | |
| 224 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) { | 206 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) { |
| 225 stream->Add("if has_cached_array_index("); | 207 stream->Add("if has_cached_array_index("); |
| 226 value()->PrintTo(stream); | 208 value()->PrintTo(stream); |
| 227 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 209 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 228 } | 210 } |
| 229 | 211 |
| 230 | |
| 231 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { | 212 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { |
| 232 stream->Add("if class_of_test("); | 213 stream->Add("if class_of_test("); |
| 233 value()->PrintTo(stream); | 214 value()->PrintTo(stream); |
| 234 stream->Add(", \"%o\") then B%d else B%d", *hydrogen()->class_name(), | 215 stream->Add(", \"%o\") then B%d else B%d", *hydrogen()->class_name(), |
| 235 true_block_id(), false_block_id()); | 216 true_block_id(), false_block_id()); |
| 236 } | 217 } |
| 237 | 218 |
| 238 | |
| 239 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { | 219 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { |
| 240 stream->Add("if typeof "); | 220 stream->Add("if typeof "); |
| 241 value()->PrintTo(stream); | 221 value()->PrintTo(stream); |
| 242 stream->Add(" == \"%s\" then B%d else B%d", | 222 stream->Add(" == \"%s\" then B%d else B%d", |
| 243 hydrogen()->type_literal()->ToCString().get(), true_block_id(), | 223 hydrogen()->type_literal()->ToCString().get(), true_block_id(), |
| 244 false_block_id()); | 224 false_block_id()); |
| 245 } | 225 } |
| 246 | 226 |
| 247 | |
| 248 void LStoreCodeEntry::PrintDataTo(StringStream* stream) { | 227 void LStoreCodeEntry::PrintDataTo(StringStream* stream) { |
| 249 stream->Add(" = "); | 228 stream->Add(" = "); |
| 250 function()->PrintTo(stream); | 229 function()->PrintTo(stream); |
| 251 stream->Add(".code_entry = "); | 230 stream->Add(".code_entry = "); |
| 252 code_object()->PrintTo(stream); | 231 code_object()->PrintTo(stream); |
| 253 } | 232 } |
| 254 | 233 |
| 255 | |
| 256 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) { | 234 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) { |
| 257 stream->Add(" = "); | 235 stream->Add(" = "); |
| 258 base_object()->PrintTo(stream); | 236 base_object()->PrintTo(stream); |
| 259 stream->Add(" + "); | 237 stream->Add(" + "); |
| 260 offset()->PrintTo(stream); | 238 offset()->PrintTo(stream); |
| 261 } | 239 } |
| 262 | 240 |
| 263 | |
| 264 void LCallWithDescriptor::PrintDataTo(StringStream* stream) { | 241 void LCallWithDescriptor::PrintDataTo(StringStream* stream) { |
| 265 for (int i = 0; i < InputCount(); i++) { | 242 for (int i = 0; i < InputCount(); i++) { |
| 266 InputAt(i)->PrintTo(stream); | 243 InputAt(i)->PrintTo(stream); |
| 267 stream->Add(" "); | 244 stream->Add(" "); |
| 268 } | 245 } |
| 269 stream->Add("#%d / ", arity()); | 246 stream->Add("#%d / ", arity()); |
| 270 } | 247 } |
| 271 | 248 |
| 272 | |
| 273 void LLoadContextSlot::PrintDataTo(StringStream* stream) { | 249 void LLoadContextSlot::PrintDataTo(StringStream* stream) { |
| 274 context()->PrintTo(stream); | 250 context()->PrintTo(stream); |
| 275 stream->Add("[%d]", slot_index()); | 251 stream->Add("[%d]", slot_index()); |
| 276 } | 252 } |
| 277 | 253 |
| 278 | |
| 279 void LStoreContextSlot::PrintDataTo(StringStream* stream) { | 254 void LStoreContextSlot::PrintDataTo(StringStream* stream) { |
| 280 context()->PrintTo(stream); | 255 context()->PrintTo(stream); |
| 281 stream->Add("[%d] <- ", slot_index()); | 256 stream->Add("[%d] <- ", slot_index()); |
| 282 value()->PrintTo(stream); | 257 value()->PrintTo(stream); |
| 283 } | 258 } |
| 284 | 259 |
| 285 | |
| 286 void LInvokeFunction::PrintDataTo(StringStream* stream) { | 260 void LInvokeFunction::PrintDataTo(StringStream* stream) { |
| 287 stream->Add("= "); | 261 stream->Add("= "); |
| 288 function()->PrintTo(stream); | 262 function()->PrintTo(stream); |
| 289 stream->Add(" #%d / ", arity()); | 263 stream->Add(" #%d / ", arity()); |
| 290 } | 264 } |
| 291 | 265 |
| 292 | |
| 293 void LCallNewArray::PrintDataTo(StringStream* stream) { | 266 void LCallNewArray::PrintDataTo(StringStream* stream) { |
| 294 stream->Add("= "); | 267 stream->Add("= "); |
| 295 constructor()->PrintTo(stream); | 268 constructor()->PrintTo(stream); |
| 296 stream->Add(" #%d / ", arity()); | 269 stream->Add(" #%d / ", arity()); |
| 297 ElementsKind kind = hydrogen()->elements_kind(); | 270 ElementsKind kind = hydrogen()->elements_kind(); |
| 298 stream->Add(" (%s) ", ElementsKindToString(kind)); | 271 stream->Add(" (%s) ", ElementsKindToString(kind)); |
| 299 } | 272 } |
| 300 | 273 |
| 301 | |
| 302 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { | 274 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { |
| 303 arguments()->PrintTo(stream); | 275 arguments()->PrintTo(stream); |
| 304 stream->Add(" length "); | 276 stream->Add(" length "); |
| 305 length()->PrintTo(stream); | 277 length()->PrintTo(stream); |
| 306 stream->Add(" index "); | 278 stream->Add(" index "); |
| 307 index()->PrintTo(stream); | 279 index()->PrintTo(stream); |
| 308 } | 280 } |
| 309 | 281 |
| 310 | |
| 311 void LStoreNamedField::PrintDataTo(StringStream* stream) { | 282 void LStoreNamedField::PrintDataTo(StringStream* stream) { |
| 312 object()->PrintTo(stream); | 283 object()->PrintTo(stream); |
| 313 std::ostringstream os; | 284 std::ostringstream os; |
| 314 os << hydrogen()->access() << " <- "; | 285 os << hydrogen()->access() << " <- "; |
| 315 stream->Add(os.str().c_str()); | 286 stream->Add(os.str().c_str()); |
| 316 value()->PrintTo(stream); | 287 value()->PrintTo(stream); |
| 317 } | 288 } |
| 318 | 289 |
| 319 | |
| 320 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) { | 290 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) { |
| 321 object()->PrintTo(stream); | 291 object()->PrintTo(stream); |
| 322 stream->Add("."); | 292 stream->Add("."); |
| 323 stream->Add(String::cast(*name())->ToCString().get()); | 293 stream->Add(String::cast(*name())->ToCString().get()); |
| 324 stream->Add(" <- "); | 294 stream->Add(" <- "); |
| 325 value()->PrintTo(stream); | 295 value()->PrintTo(stream); |
| 326 } | 296 } |
| 327 | 297 |
| 328 | |
| 329 void LLoadKeyed::PrintDataTo(StringStream* stream) { | 298 void LLoadKeyed::PrintDataTo(StringStream* stream) { |
| 330 elements()->PrintTo(stream); | 299 elements()->PrintTo(stream); |
| 331 stream->Add("["); | 300 stream->Add("["); |
| 332 key()->PrintTo(stream); | 301 key()->PrintTo(stream); |
| 333 if (hydrogen()->IsDehoisted()) { | 302 if (hydrogen()->IsDehoisted()) { |
| 334 stream->Add(" + %d]", base_offset()); | 303 stream->Add(" + %d]", base_offset()); |
| 335 } else { | 304 } else { |
| 336 stream->Add("]"); | 305 stream->Add("]"); |
| 337 } | 306 } |
| 338 } | 307 } |
| 339 | 308 |
| 340 | |
| 341 void LStoreKeyed::PrintDataTo(StringStream* stream) { | 309 void LStoreKeyed::PrintDataTo(StringStream* stream) { |
| 342 elements()->PrintTo(stream); | 310 elements()->PrintTo(stream); |
| 343 stream->Add("["); | 311 stream->Add("["); |
| 344 key()->PrintTo(stream); | 312 key()->PrintTo(stream); |
| 345 if (hydrogen()->IsDehoisted()) { | 313 if (hydrogen()->IsDehoisted()) { |
| 346 stream->Add(" + %d] <-", base_offset()); | 314 stream->Add(" + %d] <-", base_offset()); |
| 347 } else { | 315 } else { |
| 348 stream->Add("] <- "); | 316 stream->Add("] <- "); |
| 349 } | 317 } |
| 350 | 318 |
| 351 if (value() == NULL) { | 319 if (value() == NULL) { |
| 352 DCHECK(hydrogen()->IsConstantHoleStore() && | 320 DCHECK(hydrogen()->IsConstantHoleStore() && |
| 353 hydrogen()->value()->representation().IsDouble()); | 321 hydrogen()->value()->representation().IsDouble()); |
| 354 stream->Add("<the hole(nan)>"); | 322 stream->Add("<the hole(nan)>"); |
| 355 } else { | 323 } else { |
| 356 value()->PrintTo(stream); | 324 value()->PrintTo(stream); |
| 357 } | 325 } |
| 358 } | 326 } |
| 359 | 327 |
| 360 | |
| 361 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { | 328 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { |
| 362 object()->PrintTo(stream); | 329 object()->PrintTo(stream); |
| 363 stream->Add("["); | 330 stream->Add("["); |
| 364 key()->PrintTo(stream); | 331 key()->PrintTo(stream); |
| 365 stream->Add("] <- "); | 332 stream->Add("] <- "); |
| 366 value()->PrintTo(stream); | 333 value()->PrintTo(stream); |
| 367 } | 334 } |
| 368 | 335 |
| 369 | |
| 370 void LTransitionElementsKind::PrintDataTo(StringStream* stream) { | 336 void LTransitionElementsKind::PrintDataTo(StringStream* stream) { |
| 371 object()->PrintTo(stream); | 337 object()->PrintTo(stream); |
| 372 stream->Add(" %p -> %p", *original_map(), *transitioned_map()); | 338 stream->Add(" %p -> %p", *original_map(), *transitioned_map()); |
| 373 } | 339 } |
| 374 | 340 |
| 375 | |
| 376 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) { | 341 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) { |
| 377 // Skip a slot if for a double-width slot. | 342 // Skip a slot if for a double-width slot. |
| 378 if (kind == DOUBLE_REGISTERS) current_frame_slots_++; | 343 if (kind == DOUBLE_REGISTERS) current_frame_slots_++; |
| 379 return current_frame_slots_++; | 344 return current_frame_slots_++; |
| 380 } | 345 } |
| 381 | 346 |
| 382 | |
| 383 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { | 347 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { |
| 384 int index = GetNextSpillIndex(kind); | 348 int index = GetNextSpillIndex(kind); |
| 385 if (kind == DOUBLE_REGISTERS) { | 349 if (kind == DOUBLE_REGISTERS) { |
| 386 return LDoubleStackSlot::Create(index, zone()); | 350 return LDoubleStackSlot::Create(index, zone()); |
| 387 } else { | 351 } else { |
| 388 DCHECK(kind == GENERAL_REGISTERS); | 352 DCHECK(kind == GENERAL_REGISTERS); |
| 389 return LStackSlot::Create(index, zone()); | 353 return LStackSlot::Create(index, zone()); |
| 390 } | 354 } |
| 391 } | 355 } |
| 392 | 356 |
| 393 | |
| 394 LPlatformChunk* LChunkBuilder::Build() { | 357 LPlatformChunk* LChunkBuilder::Build() { |
| 395 DCHECK(is_unused()); | 358 DCHECK(is_unused()); |
| 396 chunk_ = new (zone()) LPlatformChunk(info(), graph()); | 359 chunk_ = new (zone()) LPlatformChunk(info(), graph()); |
| 397 LPhase phase("L_Building chunk", chunk_); | 360 LPhase phase("L_Building chunk", chunk_); |
| 398 status_ = BUILDING; | 361 status_ = BUILDING; |
| 399 | 362 |
| 400 // If compiling for OSR, reserve space for the unoptimized frame, | 363 // If compiling for OSR, reserve space for the unoptimized frame, |
| 401 // which will be subsumed into this frame. | 364 // which will be subsumed into this frame. |
| 402 if (graph()->has_osr()) { | 365 if (graph()->has_osr()) { |
| 403 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { | 366 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { |
| 404 chunk_->GetNextSpillIndex(GENERAL_REGISTERS); | 367 chunk_->GetNextSpillIndex(GENERAL_REGISTERS); |
| 405 } | 368 } |
| 406 } | 369 } |
| 407 | 370 |
| 408 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 371 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); |
| 409 for (int i = 0; i < blocks->length(); i++) { | 372 for (int i = 0; i < blocks->length(); i++) { |
| 410 HBasicBlock* next = NULL; | 373 HBasicBlock* next = NULL; |
| 411 if (i < blocks->length() - 1) next = blocks->at(i + 1); | 374 if (i < blocks->length() - 1) next = blocks->at(i + 1); |
| 412 DoBasicBlock(blocks->at(i), next); | 375 DoBasicBlock(blocks->at(i), next); |
| 413 if (is_aborted()) return NULL; | 376 if (is_aborted()) return NULL; |
| 414 } | 377 } |
| 415 status_ = DONE; | 378 status_ = DONE; |
| 416 return chunk_; | 379 return chunk_; |
| 417 } | 380 } |
| 418 | 381 |
| 419 | |
| 420 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) { | 382 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) { |
| 421 return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code()); | 383 return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code()); |
| 422 } | 384 } |
| 423 | 385 |
| 424 | |
| 425 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) { | 386 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) { |
| 426 return new (zone()) | 387 return new (zone()) |
| 427 LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code()); | 388 LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code()); |
| 428 } | 389 } |
| 429 | 390 |
| 430 | |
| 431 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) { | 391 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) { |
| 432 return Use(value, ToUnallocated(fixed_register)); | 392 return Use(value, ToUnallocated(fixed_register)); |
| 433 } | 393 } |
| 434 | 394 |
| 435 | |
| 436 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) { | 395 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) { |
| 437 return Use(value, ToUnallocated(reg)); | 396 return Use(value, ToUnallocated(reg)); |
| 438 } | 397 } |
| 439 | 398 |
| 440 | |
| 441 LOperand* LChunkBuilder::UseRegister(HValue* value) { | 399 LOperand* LChunkBuilder::UseRegister(HValue* value) { |
| 442 return Use(value, | 400 return Use(value, |
| 443 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); | 401 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); |
| 444 } | 402 } |
| 445 | 403 |
| 446 | |
| 447 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) { | 404 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) { |
| 448 return Use(value, new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER, | 405 return Use(value, new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER, |
| 449 LUnallocated::USED_AT_START)); | 406 LUnallocated::USED_AT_START)); |
| 450 } | 407 } |
| 451 | 408 |
| 452 | |
| 453 LOperand* LChunkBuilder::UseTempRegister(HValue* value) { | 409 LOperand* LChunkBuilder::UseTempRegister(HValue* value) { |
| 454 return Use(value, new (zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER)); | 410 return Use(value, new (zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER)); |
| 455 } | 411 } |
| 456 | 412 |
| 457 | |
| 458 LOperand* LChunkBuilder::Use(HValue* value) { | 413 LOperand* LChunkBuilder::Use(HValue* value) { |
| 459 return Use(value, new (zone()) LUnallocated(LUnallocated::NONE)); | 414 return Use(value, new (zone()) LUnallocated(LUnallocated::NONE)); |
| 460 } | 415 } |
| 461 | 416 |
| 462 | |
| 463 LOperand* LChunkBuilder::UseAtStart(HValue* value) { | 417 LOperand* LChunkBuilder::UseAtStart(HValue* value) { |
| 464 return Use(value, new (zone()) | 418 return Use(value, new (zone()) LUnallocated(LUnallocated::NONE, |
| 465 LUnallocated(LUnallocated::NONE, LUnallocated::USED_AT_START)); | 419 LUnallocated::USED_AT_START)); |
| 466 } | 420 } |
| 467 | 421 |
| 468 | |
| 469 LOperand* LChunkBuilder::UseOrConstant(HValue* value) { | 422 LOperand* LChunkBuilder::UseOrConstant(HValue* value) { |
| 470 return value->IsConstant() | 423 return value->IsConstant() |
| 471 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 424 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
| 472 : Use(value); | 425 : Use(value); |
| 473 } | 426 } |
| 474 | 427 |
| 475 | |
| 476 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) { | 428 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) { |
| 477 return value->IsConstant() | 429 return value->IsConstant() |
| 478 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 430 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
| 479 : UseAtStart(value); | 431 : UseAtStart(value); |
| 480 } | 432 } |
| 481 | 433 |
| 482 | |
| 483 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) { | 434 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) { |
| 484 return value->IsConstant() | 435 return value->IsConstant() |
| 485 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 436 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
| 486 : UseRegister(value); | 437 : UseRegister(value); |
| 487 } | 438 } |
| 488 | 439 |
| 489 | |
| 490 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { | 440 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { |
| 491 return value->IsConstant() | 441 return value->IsConstant() |
| 492 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 442 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
| 493 : UseRegisterAtStart(value); | 443 : UseRegisterAtStart(value); |
| 494 } | 444 } |
| 495 | 445 |
| 496 | |
| 497 LOperand* LChunkBuilder::UseConstant(HValue* value) { | 446 LOperand* LChunkBuilder::UseConstant(HValue* value) { |
| 498 return chunk_->DefineConstantOperand(HConstant::cast(value)); | 447 return chunk_->DefineConstantOperand(HConstant::cast(value)); |
| 499 } | 448 } |
| 500 | 449 |
| 501 | |
| 502 LOperand* LChunkBuilder::UseAny(HValue* value) { | 450 LOperand* LChunkBuilder::UseAny(HValue* value) { |
| 503 return value->IsConstant() | 451 return value->IsConstant() |
| 504 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 452 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
| 505 : Use(value, new (zone()) LUnallocated(LUnallocated::ANY)); | 453 : Use(value, new (zone()) LUnallocated(LUnallocated::ANY)); |
| 506 } | 454 } |
| 507 | 455 |
| 508 | |
| 509 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { | 456 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { |
| 510 if (value->EmitAtUses()) { | 457 if (value->EmitAtUses()) { |
| 511 HInstruction* instr = HInstruction::cast(value); | 458 HInstruction* instr = HInstruction::cast(value); |
| 512 VisitInstruction(instr); | 459 VisitInstruction(instr); |
| 513 } | 460 } |
| 514 operand->set_virtual_register(value->id()); | 461 operand->set_virtual_register(value->id()); |
| 515 return operand; | 462 return operand; |
| 516 } | 463 } |
| 517 | 464 |
| 518 | |
| 519 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr, | 465 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr, |
| 520 LUnallocated* result) { | 466 LUnallocated* result) { |
| 521 result->set_virtual_register(current_instruction_->id()); | 467 result->set_virtual_register(current_instruction_->id()); |
| 522 instr->set_result(result); | 468 instr->set_result(result); |
| 523 return instr; | 469 return instr; |
| 524 } | 470 } |
| 525 | 471 |
| 526 | |
| 527 LInstruction* LChunkBuilder::DefineAsRegister( | 472 LInstruction* LChunkBuilder::DefineAsRegister( |
| 528 LTemplateResultInstruction<1>* instr) { | 473 LTemplateResultInstruction<1>* instr) { |
| 529 return Define(instr, | 474 return Define(instr, |
| 530 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); | 475 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); |
| 531 } | 476 } |
| 532 | 477 |
| 533 | |
| 534 LInstruction* LChunkBuilder::DefineAsSpilled( | 478 LInstruction* LChunkBuilder::DefineAsSpilled( |
| 535 LTemplateResultInstruction<1>* instr, int index) { | 479 LTemplateResultInstruction<1>* instr, int index) { |
| 536 return Define(instr, | 480 return Define(instr, |
| 537 new (zone()) LUnallocated(LUnallocated::FIXED_SLOT, index)); | 481 new (zone()) LUnallocated(LUnallocated::FIXED_SLOT, index)); |
| 538 } | 482 } |
| 539 | 483 |
| 540 | |
| 541 LInstruction* LChunkBuilder::DefineSameAsFirst( | 484 LInstruction* LChunkBuilder::DefineSameAsFirst( |
| 542 LTemplateResultInstruction<1>* instr) { | 485 LTemplateResultInstruction<1>* instr) { |
| 543 return Define(instr, | 486 return Define(instr, |
| 544 new (zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); | 487 new (zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); |
| 545 } | 488 } |
| 546 | 489 |
| 547 | |
| 548 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr, | 490 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr, |
| 549 Register reg) { | 491 Register reg) { |
| 550 return Define(instr, ToUnallocated(reg)); | 492 return Define(instr, ToUnallocated(reg)); |
| 551 } | 493 } |
| 552 | 494 |
| 553 | |
| 554 LInstruction* LChunkBuilder::DefineFixedDouble( | 495 LInstruction* LChunkBuilder::DefineFixedDouble( |
| 555 LTemplateResultInstruction<1>* instr, DoubleRegister reg) { | 496 LTemplateResultInstruction<1>* instr, DoubleRegister reg) { |
| 556 return Define(instr, ToUnallocated(reg)); | 497 return Define(instr, ToUnallocated(reg)); |
| 557 } | 498 } |
| 558 | 499 |
| 559 | |
| 560 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { | 500 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { |
| 561 HEnvironment* hydrogen_env = current_block_->last_environment(); | 501 HEnvironment* hydrogen_env = current_block_->last_environment(); |
| 562 int argument_index_accumulator = 0; | 502 int argument_index_accumulator = 0; |
| 563 ZoneList<HValue*> objects_to_materialize(0, zone()); | 503 ZoneList<HValue*> objects_to_materialize(0, zone()); |
| 564 instr->set_environment(CreateEnvironment( | 504 instr->set_environment(CreateEnvironment( |
| 565 hydrogen_env, &argument_index_accumulator, &objects_to_materialize)); | 505 hydrogen_env, &argument_index_accumulator, &objects_to_materialize)); |
| 566 return instr; | 506 return instr; |
| 567 } | 507 } |
| 568 | 508 |
| 569 | |
| 570 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, | 509 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, |
| 571 HInstruction* hinstr, | 510 HInstruction* hinstr, |
| 572 CanDeoptimize can_deoptimize) { | 511 CanDeoptimize can_deoptimize) { |
| 573 info()->MarkAsNonDeferredCalling(); | 512 info()->MarkAsNonDeferredCalling(); |
| 574 #ifdef DEBUG | 513 #ifdef DEBUG |
| 575 instr->VerifyCall(); | 514 instr->VerifyCall(); |
| 576 #endif | 515 #endif |
| 577 instr->MarkAsCall(); | 516 instr->MarkAsCall(); |
| 578 instr = AssignPointerMap(instr); | 517 instr = AssignPointerMap(instr); |
| 579 | 518 |
| 580 // If instruction does not have side-effects lazy deoptimization | 519 // If instruction does not have side-effects lazy deoptimization |
| 581 // after the call will try to deoptimize to the point before the call. | 520 // after the call will try to deoptimize to the point before the call. |
| 582 // Thus we still need to attach environment to this call even if | 521 // Thus we still need to attach environment to this call even if |
| 583 // call sequence can not deoptimize eagerly. | 522 // call sequence can not deoptimize eagerly. |
| 584 bool needs_environment = (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || | 523 bool needs_environment = (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || |
| 585 !hinstr->HasObservableSideEffects(); | 524 !hinstr->HasObservableSideEffects(); |
| 586 if (needs_environment && !instr->HasEnvironment()) { | 525 if (needs_environment && !instr->HasEnvironment()) { |
| 587 instr = AssignEnvironment(instr); | 526 instr = AssignEnvironment(instr); |
| 588 // We can't really figure out if the environment is needed or not. | 527 // We can't really figure out if the environment is needed or not. |
| 589 instr->environment()->set_has_been_used(); | 528 instr->environment()->set_has_been_used(); |
| 590 } | 529 } |
| 591 | 530 |
| 592 return instr; | 531 return instr; |
| 593 } | 532 } |
| 594 | 533 |
| 595 | |
| 596 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { | 534 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
| 597 DCHECK(!instr->HasPointerMap()); | 535 DCHECK(!instr->HasPointerMap()); |
| 598 instr->set_pointer_map(new (zone()) LPointerMap(zone())); | 536 instr->set_pointer_map(new (zone()) LPointerMap(zone())); |
| 599 return instr; | 537 return instr; |
| 600 } | 538 } |
| 601 | 539 |
| 602 | |
| 603 LUnallocated* LChunkBuilder::TempRegister() { | 540 LUnallocated* LChunkBuilder::TempRegister() { |
| 604 LUnallocated* operand = | 541 LUnallocated* operand = |
| 605 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER); | 542 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER); |
| 606 int vreg = allocator_->GetVirtualRegister(); | 543 int vreg = allocator_->GetVirtualRegister(); |
| 607 if (!allocator_->AllocationOk()) { | 544 if (!allocator_->AllocationOk()) { |
| 608 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); | 545 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); |
| 609 vreg = 0; | 546 vreg = 0; |
| 610 } | 547 } |
| 611 operand->set_virtual_register(vreg); | 548 operand->set_virtual_register(vreg); |
| 612 return operand; | 549 return operand; |
| 613 } | 550 } |
| 614 | 551 |
| 615 | |
| 616 LUnallocated* LChunkBuilder::TempDoubleRegister() { | 552 LUnallocated* LChunkBuilder::TempDoubleRegister() { |
| 617 LUnallocated* operand = | 553 LUnallocated* operand = |
| 618 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_DOUBLE_REGISTER); | 554 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_DOUBLE_REGISTER); |
| 619 int vreg = allocator_->GetVirtualRegister(); | 555 int vreg = allocator_->GetVirtualRegister(); |
| 620 if (!allocator_->AllocationOk()) { | 556 if (!allocator_->AllocationOk()) { |
| 621 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); | 557 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); |
| 622 vreg = 0; | 558 vreg = 0; |
| 623 } | 559 } |
| 624 operand->set_virtual_register(vreg); | 560 operand->set_virtual_register(vreg); |
| 625 return operand; | 561 return operand; |
| 626 } | 562 } |
| 627 | 563 |
| 628 | |
| 629 LOperand* LChunkBuilder::FixedTemp(Register reg) { | 564 LOperand* LChunkBuilder::FixedTemp(Register reg) { |
| 630 LUnallocated* operand = ToUnallocated(reg); | 565 LUnallocated* operand = ToUnallocated(reg); |
| 631 DCHECK(operand->HasFixedPolicy()); | 566 DCHECK(operand->HasFixedPolicy()); |
| 632 return operand; | 567 return operand; |
| 633 } | 568 } |
| 634 | 569 |
| 635 | |
| 636 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) { | 570 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) { |
| 637 LUnallocated* operand = ToUnallocated(reg); | 571 LUnallocated* operand = ToUnallocated(reg); |
| 638 DCHECK(operand->HasFixedPolicy()); | 572 DCHECK(operand->HasFixedPolicy()); |
| 639 return operand; | 573 return operand; |
| 640 } | 574 } |
| 641 | 575 |
| 642 | |
| 643 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { | 576 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { |
| 644 return new (zone()) LLabel(instr->block()); | 577 return new (zone()) LLabel(instr->block()); |
| 645 } | 578 } |
| 646 | 579 |
| 647 | |
| 648 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { | 580 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { |
| 649 return DefineAsRegister(new (zone()) LDummyUse(UseAny(instr->value()))); | 581 return DefineAsRegister(new (zone()) LDummyUse(UseAny(instr->value()))); |
| 650 } | 582 } |
| 651 | 583 |
| 652 | |
| 653 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { | 584 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { |
| 654 UNREACHABLE(); | 585 UNREACHABLE(); |
| 655 return NULL; | 586 return NULL; |
| 656 } | 587 } |
| 657 | 588 |
| 658 | |
| 659 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 589 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
| 660 return AssignEnvironment(new (zone()) LDeoptimize); | 590 return AssignEnvironment(new (zone()) LDeoptimize); |
| 661 } | 591 } |
| 662 | 592 |
| 663 | |
| 664 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 593 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
| 665 HBitwiseBinaryOperation* instr) { | 594 HBitwiseBinaryOperation* instr) { |
| 666 if (instr->representation().IsSmiOrInteger32()) { | 595 if (instr->representation().IsSmiOrInteger32()) { |
| 667 DCHECK(instr->left()->representation().Equals(instr->representation())); | 596 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 668 DCHECK(instr->right()->representation().Equals(instr->representation())); | 597 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 669 LOperand* left = UseRegisterAtStart(instr->left()); | 598 LOperand* left = UseRegisterAtStart(instr->left()); |
| 670 | 599 |
| 671 HValue* right_value = instr->right(); | 600 HValue* right_value = instr->right(); |
| 672 LOperand* right = NULL; | 601 LOperand* right = NULL; |
| 673 int constant_value = 0; | 602 int constant_value = 0; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 692 } | 621 } |
| 693 | 622 |
| 694 LInstruction* result = | 623 LInstruction* result = |
| 695 DefineAsRegister(new (zone()) LShiftI(op, left, right, does_deopt)); | 624 DefineAsRegister(new (zone()) LShiftI(op, left, right, does_deopt)); |
| 696 return does_deopt ? AssignEnvironment(result) : result; | 625 return does_deopt ? AssignEnvironment(result) : result; |
| 697 } else { | 626 } else { |
| 698 return DoArithmeticT(op, instr); | 627 return DoArithmeticT(op, instr); |
| 699 } | 628 } |
| 700 } | 629 } |
| 701 | 630 |
| 702 | |
| 703 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 631 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
| 704 HArithmeticBinaryOperation* instr) { | 632 HArithmeticBinaryOperation* instr) { |
| 705 DCHECK(instr->representation().IsDouble()); | 633 DCHECK(instr->representation().IsDouble()); |
| 706 DCHECK(instr->left()->representation().IsDouble()); | 634 DCHECK(instr->left()->representation().IsDouble()); |
| 707 DCHECK(instr->right()->representation().IsDouble()); | 635 DCHECK(instr->right()->representation().IsDouble()); |
| 708 if (op == Token::MOD) { | 636 if (op == Token::MOD) { |
| 709 LOperand* left = UseFixedDouble(instr->left(), d1); | 637 LOperand* left = UseFixedDouble(instr->left(), d1); |
| 710 LOperand* right = UseFixedDouble(instr->right(), d2); | 638 LOperand* right = UseFixedDouble(instr->right(), d2); |
| 711 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right); | 639 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right); |
| 712 // We call a C function for double modulo. It can't trigger a GC. We need | 640 // We call a C function for double modulo. It can't trigger a GC. We need |
| 713 // to use fixed result register for the call. | 641 // to use fixed result register for the call. |
| 714 // TODO(fschneider): Allow any register as input registers. | 642 // TODO(fschneider): Allow any register as input registers. |
| 715 return MarkAsCall(DefineFixedDouble(result, d1), instr); | 643 return MarkAsCall(DefineFixedDouble(result, d1), instr); |
| 716 } else { | 644 } else { |
| 717 LOperand* left = UseRegisterAtStart(instr->left()); | 645 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 718 LOperand* right = UseRegisterAtStart(instr->right()); | 646 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); |
| 719 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right); | 647 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right); |
| 720 return DefineAsRegister(result); | 648 return DefineSameAsFirst(result); |
| 721 } | 649 } |
| 722 } | 650 } |
| 723 | 651 |
| 724 | |
| 725 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 652 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 726 HBinaryOperation* instr) { | 653 HBinaryOperation* instr) { |
| 727 HValue* left = instr->left(); | 654 HValue* left = instr->left(); |
| 728 HValue* right = instr->right(); | 655 HValue* right = instr->right(); |
| 729 DCHECK(left->representation().IsTagged()); | 656 DCHECK(left->representation().IsTagged()); |
| 730 DCHECK(right->representation().IsTagged()); | 657 DCHECK(right->representation().IsTagged()); |
| 731 LOperand* context = UseFixed(instr->context(), cp); | 658 LOperand* context = UseFixed(instr->context(), cp); |
| 732 LOperand* left_operand = UseFixed(left, r4); | 659 LOperand* left_operand = UseFixed(left, r3); |
| 733 LOperand* right_operand = UseFixed(right, r3); | 660 LOperand* right_operand = UseFixed(right, r2); |
| 734 LArithmeticT* result = | 661 LArithmeticT* result = |
| 735 new (zone()) LArithmeticT(op, context, left_operand, right_operand); | 662 new (zone()) LArithmeticT(op, context, left_operand, right_operand); |
| 736 return MarkAsCall(DefineFixed(result, r3), instr); | 663 return MarkAsCall(DefineFixed(result, r2), instr); |
| 737 } | 664 } |
| 738 | 665 |
| 739 | |
| 740 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { | 666 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { |
| 741 DCHECK(is_building()); | 667 DCHECK(is_building()); |
| 742 current_block_ = block; | 668 current_block_ = block; |
| 743 next_block_ = next_block; | 669 next_block_ = next_block; |
| 744 if (block->IsStartBlock()) { | 670 if (block->IsStartBlock()) { |
| 745 block->UpdateEnvironment(graph_->start_environment()); | 671 block->UpdateEnvironment(graph_->start_environment()); |
| 746 argument_count_ = 0; | 672 argument_count_ = 0; |
| 747 } else if (block->predecessors()->length() == 1) { | 673 } else if (block->predecessors()->length() == 1) { |
| 748 // We have a single predecessor => copy environment and outgoing | 674 // We have a single predecessor => copy environment and outgoing |
| 749 // argument count from the predecessor. | 675 // argument count from the predecessor. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 int end = chunk_->instructions()->length() - 1; | 722 int end = chunk_->instructions()->length() - 1; |
| 797 if (end >= start) { | 723 if (end >= start) { |
| 798 block->set_first_instruction_index(start); | 724 block->set_first_instruction_index(start); |
| 799 block->set_last_instruction_index(end); | 725 block->set_last_instruction_index(end); |
| 800 } | 726 } |
| 801 block->set_argument_count(argument_count_); | 727 block->set_argument_count(argument_count_); |
| 802 next_block_ = NULL; | 728 next_block_ = NULL; |
| 803 current_block_ = NULL; | 729 current_block_ = NULL; |
| 804 } | 730 } |
| 805 | 731 |
| 806 | |
| 807 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 732 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
| 808 HInstruction* old_current = current_instruction_; | 733 HInstruction* old_current = current_instruction_; |
| 809 current_instruction_ = current; | 734 current_instruction_ = current; |
| 810 | 735 |
| 811 LInstruction* instr = NULL; | 736 LInstruction* instr = NULL; |
| 812 if (current->CanReplaceWithDummyUses()) { | 737 if (current->CanReplaceWithDummyUses()) { |
| 813 if (current->OperandCount() == 0) { | 738 if (current->OperandCount() == 0) { |
| 814 instr = DefineAsRegister(new (zone()) LDummy()); | 739 instr = DefineAsRegister(new (zone()) LDummy()); |
| 815 } else { | 740 } else { |
| 816 DCHECK(!current->OperandAt(0)->IsControlInstruction()); | 741 DCHECK(!current->OperandAt(0)->IsControlInstruction()); |
| 817 instr = DefineAsRegister(new (zone()) | 742 instr = DefineAsRegister(new (zone()) |
| 818 LDummyUse(UseAny(current->OperandAt(0)))); | 743 LDummyUse(UseAny(current->OperandAt(0)))); |
| 819 } | 744 } |
| 820 for (int i = 1; i < current->OperandCount(); ++i) { | 745 for (int i = 1; i < current->OperandCount(); ++i) { |
| 821 if (current->OperandAt(i)->IsControlInstruction()) continue; | 746 if (current->OperandAt(i)->IsControlInstruction()) continue; |
| 822 LInstruction* dummy = | 747 LInstruction* dummy = |
| 823 new (zone()) LDummyUse(UseAny(current->OperandAt(i))); | 748 new (zone()) LDummyUse(UseAny(current->OperandAt(i))); |
| 824 dummy->set_hydrogen_value(current); | 749 dummy->set_hydrogen_value(current); |
| 825 chunk_->AddInstruction(dummy, current_block_); | 750 chunk_->AddInstruction(dummy, current_block_); |
| 826 } | 751 } |
| 827 } else { | 752 } else { |
| 828 HBasicBlock* successor; | 753 HBasicBlock* successor; |
| 829 if (current->IsControlInstruction() && | 754 if (current->IsControlInstruction() && |
| 830 HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) && | 755 HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) && |
| 831 successor != NULL) { | 756 successor != NULL) { |
| 832 instr = new (zone()) LGoto(successor); | 757 instr = new (zone()) LGoto(successor); |
| 833 } else { | 758 } else { |
| 834 instr = current->CompileToLithium(this); | 759 instr = current->CompileToLithium(this); |
| 835 } | 760 } |
| 836 } | 761 } |
| 837 | 762 |
| 838 argument_count_ += current->argument_delta(); | 763 argument_count_ += current->argument_delta(); |
| 839 DCHECK(argument_count_ >= 0); | 764 DCHECK(argument_count_ >= 0); |
| 840 | 765 |
| 841 if (instr != NULL) { | 766 if (instr != NULL) { |
| 842 AddInstruction(instr, current); | 767 AddInstruction(instr, current); |
| 843 } | 768 } |
| 844 | 769 |
| 845 current_instruction_ = old_current; | 770 current_instruction_ = old_current; |
| 846 } | 771 } |
| 847 | 772 |
| 848 | |
| 849 void LChunkBuilder::AddInstruction(LInstruction* instr, | 773 void LChunkBuilder::AddInstruction(LInstruction* instr, |
| 850 HInstruction* hydrogen_val) { | 774 HInstruction* hydrogen_val) { |
| 851 // Associate the hydrogen instruction first, since we may need it for | 775 // Associate the hydrogen instruction first, since we may need it for |
| 852 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. | 776 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. |
| 853 instr->set_hydrogen_value(hydrogen_val); | 777 instr->set_hydrogen_value(hydrogen_val); |
| 854 | 778 |
| 855 #if DEBUG | 779 #if DEBUG |
| 856 // Make sure that the lithium instruction has either no fixed register | 780 // Make sure that the lithium instruction has either no fixed register |
| 857 // constraints in temps or the result OR no uses that are only used at | 781 // constraints in temps or the result OR no uses that are only used at |
| 858 // start. If this invariant doesn't hold, the register allocator can decide | 782 // start. If this invariant doesn't hold, the register allocator can decide |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 896 HSimulate* sim = HSimulate::cast(hydrogen_val->next()); | 820 HSimulate* sim = HSimulate::cast(hydrogen_val->next()); |
| 897 sim->ReplayEnvironment(current_block_->last_environment()); | 821 sim->ReplayEnvironment(current_block_->last_environment()); |
| 898 hydrogen_value_for_lazy_bailout = sim; | 822 hydrogen_value_for_lazy_bailout = sim; |
| 899 } | 823 } |
| 900 LInstruction* bailout = AssignEnvironment(new (zone()) LLazyBailout()); | 824 LInstruction* bailout = AssignEnvironment(new (zone()) LLazyBailout()); |
| 901 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); | 825 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); |
| 902 chunk_->AddInstruction(bailout, current_block_); | 826 chunk_->AddInstruction(bailout, current_block_); |
| 903 } | 827 } |
| 904 } | 828 } |
| 905 | 829 |
| 906 | |
| 907 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) { | 830 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) { |
| 908 return new (zone()) LPrologue(); | 831 return new (zone()) LPrologue(); |
| 909 } | 832 } |
| 910 | 833 |
| 911 | |
| 912 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 834 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 913 return new (zone()) LGoto(instr->FirstSuccessor()); | 835 return new (zone()) LGoto(instr->FirstSuccessor()); |
| 914 } | 836 } |
| 915 | 837 |
| 916 | |
| 917 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 838 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
| 918 HValue* value = instr->value(); | 839 HValue* value = instr->value(); |
| 919 Representation r = value->representation(); | 840 Representation r = value->representation(); |
| 920 HType type = value->type(); | 841 HType type = value->type(); |
| 921 ToBooleanICStub::Types expected = instr->expected_input_types(); | 842 ToBooleanStub::Types expected = instr->expected_input_types(); |
| 922 if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic(); | 843 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
| 923 | 844 |
| 924 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() || | 845 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() || |
| 925 type.IsJSArray() || type.IsHeapNumber() || type.IsString(); | 846 type.IsJSArray() || type.IsHeapNumber() || type.IsString(); |
| 926 LInstruction* branch = new (zone()) LBranch(UseRegister(value)); | 847 LInstruction* branch = new (zone()) LBranch(UseRegister(value)); |
| 927 if (!easy_case && | 848 if (!easy_case && |
| 928 ((!expected.Contains(ToBooleanICStub::SMI) && expected.NeedsMap()) || | 849 ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) || |
| 929 !expected.IsGeneric())) { | 850 !expected.IsGeneric())) { |
| 930 branch = AssignEnvironment(branch); | 851 branch = AssignEnvironment(branch); |
| 931 } | 852 } |
| 932 return branch; | 853 return branch; |
| 933 } | 854 } |
| 934 | 855 |
| 935 | |
| 936 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { | 856 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { |
| 937 return new (zone()) LDebugBreak(); | 857 return new (zone()) LDebugBreak(); |
| 938 } | 858 } |
| 939 | 859 |
| 940 | |
| 941 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 860 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| 942 DCHECK(instr->value()->representation().IsTagged()); | 861 DCHECK(instr->value()->representation().IsTagged()); |
| 943 LOperand* value = UseRegisterAtStart(instr->value()); | 862 LOperand* value = UseRegister(instr->value()); |
| 944 LOperand* temp = TempRegister(); | 863 LOperand* temp = TempRegister(); |
| 945 return new (zone()) LCmpMapAndBranch(value, temp); | 864 return new (zone()) LCmpMapAndBranch(value, temp); |
| 946 } | 865 } |
| 947 | 866 |
| 948 | |
| 949 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) { | 867 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) { |
| 950 info()->MarkAsRequiresFrame(); | 868 info()->MarkAsRequiresFrame(); |
| 951 LOperand* value = UseRegister(instr->value()); | 869 LOperand* value = UseRegister(instr->value()); |
| 952 return DefineAsRegister(new (zone()) LArgumentsLength(value)); | 870 return DefineAsRegister(new (zone()) LArgumentsLength(value)); |
| 953 } | 871 } |
| 954 | 872 |
| 955 | |
| 956 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { | 873 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { |
| 957 info()->MarkAsRequiresFrame(); | 874 info()->MarkAsRequiresFrame(); |
| 958 return DefineAsRegister(new (zone()) LArgumentsElements); | 875 return DefineAsRegister(new (zone()) LArgumentsElements); |
| 959 } | 876 } |
| 960 | 877 |
| 961 | |
| 962 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { | 878 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { |
| 963 LOperand* left = | 879 LOperand* left = |
| 964 UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister()); | 880 UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister()); |
| 965 LOperand* right = | 881 LOperand* right = |
| 966 UseFixed(instr->right(), InstanceOfDescriptor::RightRegister()); | 882 UseFixed(instr->right(), InstanceOfDescriptor::RightRegister()); |
| 967 LOperand* context = UseFixed(instr->context(), cp); | 883 LOperand* context = UseFixed(instr->context(), cp); |
| 968 LInstanceOf* result = new (zone()) LInstanceOf(context, left, right); | 884 LInstanceOf* result = new (zone()) LInstanceOf(context, left, right); |
| 969 return MarkAsCall(DefineFixed(result, r3), instr); | 885 return MarkAsCall(DefineFixed(result, r2), instr); |
| 970 } | 886 } |
| 971 | 887 |
| 972 | |
| 973 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch( | 888 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch( |
| 974 HHasInPrototypeChainAndBranch* instr) { | 889 HHasInPrototypeChainAndBranch* instr) { |
| 975 LOperand* object = UseRegister(instr->object()); | 890 LOperand* object = UseRegister(instr->object()); |
| 976 LOperand* prototype = UseRegister(instr->prototype()); | 891 LOperand* prototype = UseRegister(instr->prototype()); |
| 977 LHasInPrototypeChainAndBranch* result = | 892 LHasInPrototypeChainAndBranch* result = |
| 978 new (zone()) LHasInPrototypeChainAndBranch(object, prototype); | 893 new (zone()) LHasInPrototypeChainAndBranch(object, prototype); |
| 979 return AssignEnvironment(result); | 894 return AssignEnvironment(result); |
| 980 } | 895 } |
| 981 | 896 |
| 982 | |
| 983 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { | 897 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { |
| 984 LOperand* receiver = UseRegisterAtStart(instr->receiver()); | 898 LOperand* receiver = UseRegisterAtStart(instr->receiver()); |
| 985 LOperand* function = UseRegisterAtStart(instr->function()); | 899 LOperand* function = UseRegisterAtStart(instr->function()); |
| 986 LWrapReceiver* result = new (zone()) LWrapReceiver(receiver, function); | 900 LWrapReceiver* result = new (zone()) LWrapReceiver(receiver, function); |
| 987 return AssignEnvironment(DefineAsRegister(result)); | 901 return AssignEnvironment(DefineAsRegister(result)); |
| 988 } | 902 } |
| 989 | 903 |
| 990 | |
| 991 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 904 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
| 992 LOperand* function = UseFixed(instr->function(), r4); | 905 LOperand* function = UseFixed(instr->function(), r3); |
| 993 LOperand* receiver = UseFixed(instr->receiver(), r3); | 906 LOperand* receiver = UseFixed(instr->receiver(), r2); |
| 994 LOperand* length = UseFixed(instr->length(), r5); | 907 LOperand* length = UseFixed(instr->length(), r4); |
| 995 LOperand* elements = UseFixed(instr->elements(), r6); | 908 LOperand* elements = UseFixed(instr->elements(), r5); |
| 996 LApplyArguments* result = | 909 LApplyArguments* result = |
| 997 new (zone()) LApplyArguments(function, receiver, length, elements); | 910 new (zone()) LApplyArguments(function, receiver, length, elements); |
| 998 return MarkAsCall(DefineFixed(result, r3), instr, CAN_DEOPTIMIZE_EAGERLY); | 911 return MarkAsCall(DefineFixed(result, r2), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 999 } | 912 } |
| 1000 | 913 |
| 1001 | |
| 1002 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) { | 914 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) { |
| 1003 int argc = instr->OperandCount(); | 915 int argc = instr->OperandCount(); |
| 1004 for (int i = 0; i < argc; ++i) { | 916 for (int i = 0; i < argc; ++i) { |
| 1005 LOperand* argument = Use(instr->argument(i)); | 917 LOperand* argument = Use(instr->argument(i)); |
| 1006 AddInstruction(new (zone()) LPushArgument(argument), instr); | 918 AddInstruction(new (zone()) LPushArgument(argument), instr); |
| 1007 } | 919 } |
| 1008 return NULL; | 920 return NULL; |
| 1009 } | 921 } |
| 1010 | 922 |
| 1011 | |
| 1012 LInstruction* LChunkBuilder::DoStoreCodeEntry( | 923 LInstruction* LChunkBuilder::DoStoreCodeEntry( |
| 1013 HStoreCodeEntry* store_code_entry) { | 924 HStoreCodeEntry* store_code_entry) { |
| 1014 LOperand* function = UseRegister(store_code_entry->function()); | 925 LOperand* function = UseRegister(store_code_entry->function()); |
| 1015 LOperand* code_object = UseTempRegister(store_code_entry->code_object()); | 926 LOperand* code_object = UseTempRegister(store_code_entry->code_object()); |
| 1016 return new (zone()) LStoreCodeEntry(function, code_object); | 927 return new (zone()) LStoreCodeEntry(function, code_object); |
| 1017 } | 928 } |
| 1018 | 929 |
| 1019 | |
| 1020 LInstruction* LChunkBuilder::DoInnerAllocatedObject( | 930 LInstruction* LChunkBuilder::DoInnerAllocatedObject( |
| 1021 HInnerAllocatedObject* instr) { | 931 HInnerAllocatedObject* instr) { |
| 1022 LOperand* base_object = UseRegisterAtStart(instr->base_object()); | 932 LOperand* base_object = UseRegisterAtStart(instr->base_object()); |
| 1023 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset()); | 933 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset()); |
| 1024 return DefineAsRegister(new (zone()) | 934 return DefineAsRegister(new (zone()) |
| 1025 LInnerAllocatedObject(base_object, offset)); | 935 LInnerAllocatedObject(base_object, offset)); |
| 1026 } | 936 } |
| 1027 | 937 |
| 1028 | |
| 1029 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) { | 938 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) { |
| 1030 return instr->HasNoUses() ? NULL | 939 return instr->HasNoUses() ? NULL |
| 1031 : DefineAsRegister(new (zone()) LThisFunction); | 940 : DefineAsRegister(new (zone()) LThisFunction); |
| 1032 } | 941 } |
| 1033 | 942 |
| 1034 | |
| 1035 LInstruction* LChunkBuilder::DoContext(HContext* instr) { | 943 LInstruction* LChunkBuilder::DoContext(HContext* instr) { |
| 1036 if (instr->HasNoUses()) return NULL; | 944 if (instr->HasNoUses()) return NULL; |
| 1037 | 945 |
| 1038 if (info()->IsStub()) { | 946 if (info()->IsStub()) { |
| 1039 return DefineFixed(new (zone()) LContext, cp); | 947 return DefineFixed(new (zone()) LContext, cp); |
| 1040 } | 948 } |
| 1041 | 949 |
| 1042 return DefineAsRegister(new (zone()) LContext); | 950 return DefineAsRegister(new (zone()) LContext); |
| 1043 } | 951 } |
| 1044 | 952 |
| 1045 | |
| 1046 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { | 953 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { |
| 1047 LOperand* context = UseFixed(instr->context(), cp); | 954 LOperand* context = UseFixed(instr->context(), cp); |
| 1048 return MarkAsCall(new (zone()) LDeclareGlobals(context), instr); | 955 return MarkAsCall(new (zone()) LDeclareGlobals(context), instr); |
| 1049 } | 956 } |
| 1050 | 957 |
| 1051 | |
| 1052 LInstruction* LChunkBuilder::DoCallWithDescriptor(HCallWithDescriptor* instr) { | 958 LInstruction* LChunkBuilder::DoCallWithDescriptor(HCallWithDescriptor* instr) { |
| 1053 CallInterfaceDescriptor descriptor = instr->descriptor(); | 959 CallInterfaceDescriptor descriptor = instr->descriptor(); |
| 1054 | 960 |
| 1055 LOperand* target = UseRegisterOrConstantAtStart(instr->target()); | 961 LOperand* target = UseRegisterOrConstantAtStart(instr->target()); |
| 1056 ZoneList<LOperand*> ops(instr->OperandCount(), zone()); | 962 ZoneList<LOperand*> ops(instr->OperandCount(), zone()); |
| 1057 // Target | 963 // Target |
| 1058 ops.Add(target, zone()); | 964 ops.Add(target, zone()); |
| 1059 // Context | 965 // Context |
| 1060 LOperand* op = UseFixed(instr->OperandAt(1), cp); | 966 LOperand* op = UseFixed(instr->OperandAt(1), cp); |
| 1061 ops.Add(op, zone()); | 967 ops.Add(op, zone()); |
| 1062 // Other register parameters | 968 // Other register parameters |
| 1063 for (int i = LCallWithDescriptor::kImplicitRegisterParameterCount; | 969 for (int i = LCallWithDescriptor::kImplicitRegisterParameterCount; |
| 1064 i < instr->OperandCount(); i++) { | 970 i < instr->OperandCount(); i++) { |
| 1065 op = | 971 op = |
| 1066 UseFixed(instr->OperandAt(i), | 972 UseFixed(instr->OperandAt(i), |
| 1067 descriptor.GetRegisterParameter( | 973 descriptor.GetRegisterParameter( |
| 1068 i - LCallWithDescriptor::kImplicitRegisterParameterCount)); | 974 i - LCallWithDescriptor::kImplicitRegisterParameterCount)); |
| 1069 ops.Add(op, zone()); | 975 ops.Add(op, zone()); |
| 1070 } | 976 } |
| 1071 | 977 |
| 1072 LCallWithDescriptor* result = | 978 LCallWithDescriptor* result = |
| 1073 new (zone()) LCallWithDescriptor(descriptor, ops, zone()); | 979 new (zone()) LCallWithDescriptor(descriptor, ops, zone()); |
| 1074 return MarkAsCall(DefineFixed(result, r3), instr); | 980 return MarkAsCall(DefineFixed(result, r2), instr); |
| 1075 } | 981 } |
| 1076 | 982 |
| 1077 | |
| 1078 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { | 983 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { |
| 1079 LOperand* context = UseFixed(instr->context(), cp); | 984 LOperand* context = UseFixed(instr->context(), cp); |
| 1080 LOperand* function = UseFixed(instr->function(), r4); | 985 LOperand* function = UseFixed(instr->function(), r3); |
| 1081 LInvokeFunction* result = new (zone()) LInvokeFunction(context, function); | 986 LInvokeFunction* result = new (zone()) LInvokeFunction(context, function); |
| 1082 return MarkAsCall(DefineFixed(result, r3), instr, CANNOT_DEOPTIMIZE_EAGERLY); | 987 return MarkAsCall(DefineFixed(result, r2), instr, CANNOT_DEOPTIMIZE_EAGERLY); |
| 1083 } | 988 } |
| 1084 | 989 |
| 1085 | |
| 1086 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 990 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1087 switch (instr->op()) { | 991 switch (instr->op()) { |
| 1088 case kMathFloor: | 992 case kMathFloor: |
| 1089 return DoMathFloor(instr); | 993 return DoMathFloor(instr); |
| 1090 case kMathRound: | 994 case kMathRound: |
| 1091 return DoMathRound(instr); | 995 return DoMathRound(instr); |
| 1092 case kMathFround: | 996 case kMathFround: |
| 1093 return DoMathFround(instr); | 997 return DoMathFround(instr); |
| 1094 case kMathAbs: | 998 case kMathAbs: |
| 1095 return DoMathAbs(instr); | 999 return DoMathAbs(instr); |
| 1096 case kMathLog: | 1000 case kMathLog: |
| 1097 return DoMathLog(instr); | 1001 return DoMathLog(instr); |
| 1098 case kMathExp: | 1002 case kMathExp: |
| 1099 return DoMathExp(instr); | 1003 return DoMathExp(instr); |
| 1100 case kMathSqrt: | 1004 case kMathSqrt: |
| 1101 return DoMathSqrt(instr); | 1005 return DoMathSqrt(instr); |
| 1102 case kMathPowHalf: | 1006 case kMathPowHalf: |
| 1103 return DoMathPowHalf(instr); | 1007 return DoMathPowHalf(instr); |
| 1104 case kMathClz32: | 1008 case kMathClz32: |
| 1105 return DoMathClz32(instr); | 1009 return DoMathClz32(instr); |
| 1106 default: | 1010 default: |
| 1107 UNREACHABLE(); | 1011 UNREACHABLE(); |
| 1108 return NULL; | 1012 return NULL; |
| 1109 } | 1013 } |
| 1110 } | 1014 } |
| 1111 | 1015 |
| 1112 | |
| 1113 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { | 1016 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { |
| 1114 LOperand* input = UseRegister(instr->value()); | 1017 LOperand* input = UseRegister(instr->value()); |
| 1115 LMathFloor* result = new (zone()) LMathFloor(input); | 1018 LMathFloor* result = new (zone()) LMathFloor(input); |
| 1116 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1019 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1117 } | 1020 } |
| 1118 | 1021 |
| 1119 | |
| 1120 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { | 1022 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { |
| 1121 LOperand* input = UseRegister(instr->value()); | 1023 LOperand* input = UseRegister(instr->value()); |
| 1122 LOperand* temp = TempDoubleRegister(); | 1024 LOperand* temp = TempDoubleRegister(); |
| 1123 LMathRound* result = new (zone()) LMathRound(input, temp); | 1025 LMathRound* result = new (zone()) LMathRound(input, temp); |
| 1124 return AssignEnvironment(DefineAsRegister(result)); | 1026 return AssignEnvironment(DefineAsRegister(result)); |
| 1125 } | 1027 } |
| 1126 | 1028 |
| 1127 | |
| 1128 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) { | 1029 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) { |
| 1129 LOperand* input = UseRegister(instr->value()); | 1030 LOperand* input = UseRegister(instr->value()); |
| 1130 LMathFround* result = new (zone()) LMathFround(input); | 1031 LMathFround* result = new (zone()) LMathFround(input); |
| 1131 return DefineAsRegister(result); | 1032 return DefineAsRegister(result); |
| 1132 } | 1033 } |
| 1133 | 1034 |
| 1134 | |
| 1135 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { | 1035 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { |
| 1136 Representation r = instr->value()->representation(); | 1036 Representation r = instr->value()->representation(); |
| 1137 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32()) | 1037 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32()) |
| 1138 ? NULL | 1038 ? NULL |
| 1139 : UseFixed(instr->context(), cp); | 1039 : UseFixed(instr->context(), cp); |
| 1140 LOperand* input = UseRegister(instr->value()); | 1040 LOperand* input = UseRegister(instr->value()); |
| 1141 LInstruction* result = | 1041 LInstruction* result = |
| 1142 DefineAsRegister(new (zone()) LMathAbs(context, input)); | 1042 DefineAsRegister(new (zone()) LMathAbs(context, input)); |
| 1143 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); | 1043 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); |
| 1144 if (!r.IsDouble()) result = AssignEnvironment(result); | 1044 if (!r.IsDouble()) result = AssignEnvironment(result); |
| 1145 return result; | 1045 return result; |
| 1146 } | 1046 } |
| 1147 | 1047 |
| 1148 | |
| 1149 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { | 1048 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { |
| 1150 DCHECK(instr->representation().IsDouble()); | 1049 DCHECK(instr->representation().IsDouble()); |
| 1151 DCHECK(instr->value()->representation().IsDouble()); | 1050 DCHECK(instr->value()->representation().IsDouble()); |
| 1152 LOperand* input = UseFixedDouble(instr->value(), d1); | 1051 LOperand* input = UseFixedDouble(instr->value(), d1); |
| 1153 return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d1), instr); | 1052 return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d1), instr); |
| 1154 } | 1053 } |
| 1155 | 1054 |
| 1156 | |
| 1157 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) { | 1055 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) { |
| 1158 LOperand* input = UseRegisterAtStart(instr->value()); | 1056 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1159 LMathClz32* result = new (zone()) LMathClz32(input); | 1057 LMathClz32* result = new (zone()) LMathClz32(input); |
| 1160 return DefineAsRegister(result); | 1058 return DefineAsRegister(result); |
| 1161 } | 1059 } |
| 1162 | 1060 |
| 1163 | |
| 1164 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { | 1061 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { |
| 1165 DCHECK(instr->representation().IsDouble()); | 1062 DCHECK(instr->representation().IsDouble()); |
| 1166 DCHECK(instr->value()->representation().IsDouble()); | 1063 DCHECK(instr->value()->representation().IsDouble()); |
| 1167 LOperand* input = UseRegister(instr->value()); | 1064 LOperand* input = UseRegister(instr->value()); |
| 1168 LOperand* temp1 = TempRegister(); | 1065 LOperand* temp1 = TempRegister(); |
| 1169 LOperand* temp2 = TempRegister(); | 1066 LOperand* temp2 = TempRegister(); |
| 1170 LOperand* double_temp = TempDoubleRegister(); | 1067 LOperand* double_temp = TempDoubleRegister(); |
| 1171 LMathExp* result = new (zone()) LMathExp(input, double_temp, temp1, temp2); | 1068 LMathExp* result = new (zone()) LMathExp(input, double_temp, temp1, temp2); |
| 1172 return DefineAsRegister(result); | 1069 return DefineAsRegister(result); |
| 1173 } | 1070 } |
| 1174 | 1071 |
| 1175 | |
| 1176 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) { | 1072 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) { |
| 1177 LOperand* input = UseRegisterAtStart(instr->value()); | 1073 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1178 LMathSqrt* result = new (zone()) LMathSqrt(input); | 1074 LMathSqrt* result = new (zone()) LMathSqrt(input); |
| 1179 return DefineAsRegister(result); | 1075 return DefineAsRegister(result); |
| 1180 } | 1076 } |
| 1181 | 1077 |
| 1182 | |
| 1183 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) { | 1078 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) { |
| 1184 LOperand* input = UseRegisterAtStart(instr->value()); | 1079 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1185 LMathPowHalf* result = new (zone()) LMathPowHalf(input); | 1080 LMathPowHalf* result = new (zone()) LMathPowHalf(input); |
| 1186 return DefineAsRegister(result); | 1081 return DefineAsRegister(result); |
| 1187 } | 1082 } |
| 1188 | 1083 |
| 1189 | |
| 1190 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { | 1084 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { |
| 1191 LOperand* context = UseFixed(instr->context(), cp); | 1085 LOperand* context = UseFixed(instr->context(), cp); |
| 1192 LOperand* constructor = UseFixed(instr->constructor(), r4); | 1086 LOperand* constructor = UseFixed(instr->constructor(), r3); |
| 1193 LCallNewArray* result = new (zone()) LCallNewArray(context, constructor); | 1087 LCallNewArray* result = new (zone()) LCallNewArray(context, constructor); |
| 1194 return MarkAsCall(DefineFixed(result, r3), instr); | 1088 return MarkAsCall(DefineFixed(result, r2), instr); |
| 1195 } | 1089 } |
| 1196 | 1090 |
| 1197 | |
| 1198 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { | 1091 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
| 1199 LOperand* context = UseFixed(instr->context(), cp); | 1092 LOperand* context = UseFixed(instr->context(), cp); |
| 1200 return MarkAsCall(DefineFixed(new (zone()) LCallRuntime(context), r3), instr); | 1093 return MarkAsCall(DefineFixed(new (zone()) LCallRuntime(context), r2), instr); |
| 1201 } | 1094 } |
| 1202 | 1095 |
| 1203 | |
| 1204 LInstruction* LChunkBuilder::DoRor(HRor* instr) { | 1096 LInstruction* LChunkBuilder::DoRor(HRor* instr) { |
| 1205 return DoShift(Token::ROR, instr); | 1097 return DoShift(Token::ROR, instr); |
| 1206 } | 1098 } |
| 1207 | 1099 |
| 1208 | |
| 1209 LInstruction* LChunkBuilder::DoShr(HShr* instr) { | 1100 LInstruction* LChunkBuilder::DoShr(HShr* instr) { |
| 1210 return DoShift(Token::SHR, instr); | 1101 return DoShift(Token::SHR, instr); |
| 1211 } | 1102 } |
| 1212 | 1103 |
| 1213 | |
| 1214 LInstruction* LChunkBuilder::DoSar(HSar* instr) { | 1104 LInstruction* LChunkBuilder::DoSar(HSar* instr) { |
| 1215 return DoShift(Token::SAR, instr); | 1105 return DoShift(Token::SAR, instr); |
| 1216 } | 1106 } |
| 1217 | 1107 |
| 1218 | |
| 1219 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1108 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
| 1220 return DoShift(Token::SHL, instr); | 1109 return DoShift(Token::SHL, instr); |
| 1221 } | 1110 } |
| 1222 | 1111 |
| 1223 | |
| 1224 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1112 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
| 1225 if (instr->representation().IsSmiOrInteger32()) { | 1113 if (instr->representation().IsSmiOrInteger32()) { |
| 1226 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1114 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1227 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1115 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1228 DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32)); | 1116 DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32)); |
| 1229 | 1117 |
| 1230 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1118 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1231 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1119 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1232 return DefineAsRegister(new (zone()) LBitI(left, right)); | 1120 return DefineAsRegister(new (zone()) LBitI(left, right)); |
| 1233 } else { | 1121 } else { |
| 1234 return DoArithmeticT(instr->op(), instr); | 1122 return DoArithmeticT(instr->op(), instr); |
| 1235 } | 1123 } |
| 1236 } | 1124 } |
| 1237 | 1125 |
| 1238 | |
| 1239 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { | 1126 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { |
| 1240 DCHECK(instr->representation().IsSmiOrInteger32()); | 1127 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1241 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1128 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1242 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1129 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1243 LOperand* dividend = UseRegister(instr->left()); | 1130 LOperand* dividend = UseRegister(instr->left()); |
| 1244 int32_t divisor = instr->right()->GetInteger32Constant(); | 1131 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1245 LInstruction* result = | 1132 LInstruction* result = |
| 1246 DefineAsRegister(new (zone()) LDivByPowerOf2I(dividend, divisor)); | 1133 DefineAsRegister(new (zone()) LDivByPowerOf2I(dividend, divisor)); |
| 1247 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1134 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1248 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) || | 1135 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) || |
| 1249 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1136 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1250 divisor != 1 && divisor != -1)) { | 1137 divisor != 1 && divisor != -1)) { |
| 1251 result = AssignEnvironment(result); | 1138 result = AssignEnvironment(result); |
| 1252 } | 1139 } |
| 1253 return result; | 1140 return result; |
| 1254 } | 1141 } |
| 1255 | 1142 |
| 1256 | |
| 1257 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { | 1143 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { |
| 1258 DCHECK(instr->representation().IsInteger32()); | 1144 DCHECK(instr->representation().IsInteger32()); |
| 1259 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1145 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1260 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1146 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1261 LOperand* dividend = UseRegister(instr->left()); | 1147 LOperand* dividend = UseRegister(instr->left()); |
| 1262 int32_t divisor = instr->right()->GetInteger32Constant(); | 1148 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1263 LInstruction* result = | 1149 LInstruction* result = |
| 1264 DefineAsRegister(new (zone()) LDivByConstI(dividend, divisor)); | 1150 DefineAsRegister(new (zone()) LDivByConstI(dividend, divisor)); |
| 1265 if (divisor == 0 || | 1151 if (divisor == 0 || |
| 1266 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1152 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1267 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1153 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1268 result = AssignEnvironment(result); | 1154 result = AssignEnvironment(result); |
| 1269 } | 1155 } |
| 1270 return result; | 1156 return result; |
| 1271 } | 1157 } |
| 1272 | 1158 |
| 1273 | |
| 1274 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) { | 1159 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) { |
| 1275 DCHECK(instr->representation().IsSmiOrInteger32()); | 1160 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1276 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1161 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1277 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1162 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1278 LOperand* dividend = UseRegister(instr->left()); | 1163 LOperand* dividend = UseRegister(instr->left()); |
| 1279 LOperand* divisor = UseRegister(instr->right()); | 1164 LOperand* divisor = UseRegister(instr->right()); |
| 1280 LInstruction* result = | 1165 LInstruction* result = |
| 1281 DefineAsRegister(new (zone()) LDivI(dividend, divisor)); | 1166 DefineAsRegister(new (zone()) LDivI(dividend, divisor)); |
| 1282 if (instr->CheckFlag(HValue::kCanBeDivByZero) || | 1167 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1283 instr->CheckFlag(HValue::kBailoutOnMinusZero) || | 1168 instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1284 (instr->CheckFlag(HValue::kCanOverflow) && | 1169 (instr->CheckFlag(HValue::kCanOverflow) && |
| 1285 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) || | 1170 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) || |
| 1286 (!instr->IsMathFloorOfDiv() && | 1171 (!instr->IsMathFloorOfDiv() && |
| 1287 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { | 1172 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
| 1288 result = AssignEnvironment(result); | 1173 result = AssignEnvironment(result); |
| 1289 } | 1174 } |
| 1290 return result; | 1175 return result; |
| 1291 } | 1176 } |
| 1292 | 1177 |
| 1293 | |
| 1294 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1178 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1295 if (instr->representation().IsSmiOrInteger32()) { | 1179 if (instr->representation().IsSmiOrInteger32()) { |
| 1296 if (instr->RightIsPowerOf2()) { | 1180 if (instr->RightIsPowerOf2()) { |
| 1297 return DoDivByPowerOf2I(instr); | 1181 return DoDivByPowerOf2I(instr); |
| 1298 } else if (instr->right()->IsConstant()) { | 1182 } else if (instr->right()->IsConstant()) { |
| 1299 return DoDivByConstI(instr); | 1183 return DoDivByConstI(instr); |
| 1300 } else { | 1184 } else { |
| 1301 return DoDivI(instr); | 1185 return DoDivI(instr); |
| 1302 } | 1186 } |
| 1303 } else if (instr->representation().IsDouble()) { | 1187 } else if (instr->representation().IsDouble()) { |
| 1304 return DoArithmeticD(Token::DIV, instr); | 1188 return DoArithmeticD(Token::DIV, instr); |
| 1305 } else { | 1189 } else { |
| 1306 return DoArithmeticT(Token::DIV, instr); | 1190 return DoArithmeticT(Token::DIV, instr); |
| 1307 } | 1191 } |
| 1308 } | 1192 } |
| 1309 | 1193 |
| 1310 | |
| 1311 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) { | 1194 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) { |
| 1312 LOperand* dividend = UseRegisterAtStart(instr->left()); | 1195 LOperand* dividend = UseRegisterAtStart(instr->left()); |
| 1313 int32_t divisor = instr->right()->GetInteger32Constant(); | 1196 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1314 LInstruction* result = | 1197 LInstruction* result = |
| 1315 DefineAsRegister(new (zone()) LFlooringDivByPowerOf2I(dividend, divisor)); | 1198 DefineAsRegister(new (zone()) LFlooringDivByPowerOf2I(dividend, divisor)); |
| 1316 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1199 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1317 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) { | 1200 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) { |
| 1318 result = AssignEnvironment(result); | 1201 result = AssignEnvironment(result); |
| 1319 } | 1202 } |
| 1320 return result; | 1203 return result; |
| 1321 } | 1204 } |
| 1322 | 1205 |
| 1323 | |
| 1324 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { | 1206 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { |
| 1325 DCHECK(instr->representation().IsInteger32()); | 1207 DCHECK(instr->representation().IsInteger32()); |
| 1326 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1208 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1327 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1209 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1328 LOperand* dividend = UseRegister(instr->left()); | 1210 LOperand* dividend = UseRegister(instr->left()); |
| 1329 int32_t divisor = instr->right()->GetInteger32Constant(); | 1211 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1330 LOperand* temp = | 1212 LOperand* temp = |
| 1331 ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) || | 1213 ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) || |
| 1332 (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) | 1214 (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) |
| 1333 ? NULL | 1215 ? NULL |
| 1334 : TempRegister(); | 1216 : TempRegister(); |
| 1335 LInstruction* result = DefineAsRegister( | 1217 LInstruction* result = DefineAsRegister( |
| 1336 new (zone()) LFlooringDivByConstI(dividend, divisor, temp)); | 1218 new (zone()) LFlooringDivByConstI(dividend, divisor, temp)); |
| 1337 if (divisor == 0 || | 1219 if (divisor == 0 || |
| 1338 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) { | 1220 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) { |
| 1339 result = AssignEnvironment(result); | 1221 result = AssignEnvironment(result); |
| 1340 } | 1222 } |
| 1341 return result; | 1223 return result; |
| 1342 } | 1224 } |
| 1343 | 1225 |
| 1344 | |
| 1345 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) { | 1226 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) { |
| 1346 DCHECK(instr->representation().IsSmiOrInteger32()); | 1227 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1347 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1228 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1348 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1229 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1349 LOperand* dividend = UseRegister(instr->left()); | 1230 LOperand* dividend = UseRegister(instr->left()); |
| 1350 LOperand* divisor = UseRegister(instr->right()); | 1231 LOperand* divisor = UseRegister(instr->right()); |
| 1351 LInstruction* result = | 1232 LInstruction* result = |
| 1352 DefineAsRegister(new (zone()) LFlooringDivI(dividend, divisor)); | 1233 DefineAsRegister(new (zone()) LFlooringDivI(dividend, divisor)); |
| 1353 if (instr->CheckFlag(HValue::kCanBeDivByZero) || | 1234 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1354 instr->CheckFlag(HValue::kBailoutOnMinusZero) || | 1235 instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1355 (instr->CheckFlag(HValue::kCanOverflow) && | 1236 (instr->CheckFlag(HValue::kCanOverflow) && |
| 1356 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { | 1237 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
| 1357 result = AssignEnvironment(result); | 1238 result = AssignEnvironment(result); |
| 1358 } | 1239 } |
| 1359 return result; | 1240 return result; |
| 1360 } | 1241 } |
| 1361 | 1242 |
| 1362 | |
| 1363 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { | 1243 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
| 1364 if (instr->RightIsPowerOf2()) { | 1244 if (instr->RightIsPowerOf2()) { |
| 1365 return DoFlooringDivByPowerOf2I(instr); | 1245 return DoFlooringDivByPowerOf2I(instr); |
| 1366 } else if (instr->right()->IsConstant()) { | 1246 } else if (instr->right()->IsConstant()) { |
| 1367 return DoFlooringDivByConstI(instr); | 1247 return DoFlooringDivByConstI(instr); |
| 1368 } else { | 1248 } else { |
| 1369 return DoFlooringDivI(instr); | 1249 return DoFlooringDivI(instr); |
| 1370 } | 1250 } |
| 1371 } | 1251 } |
| 1372 | 1252 |
| 1373 | |
| 1374 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { | 1253 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { |
| 1375 DCHECK(instr->representation().IsSmiOrInteger32()); | 1254 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1376 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1255 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1377 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1256 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1378 LOperand* dividend = UseRegisterAtStart(instr->left()); | 1257 LOperand* dividend = UseRegisterAtStart(instr->left()); |
| 1379 int32_t divisor = instr->right()->GetInteger32Constant(); | 1258 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1380 LInstruction* result = | 1259 LInstruction* result = |
| 1381 DefineSameAsFirst(new (zone()) LModByPowerOf2I(dividend, divisor)); | 1260 DefineSameAsFirst(new (zone()) LModByPowerOf2I(dividend, divisor)); |
| 1382 if (instr->CheckFlag(HValue::kLeftCanBeNegative) && | 1261 if (instr->CheckFlag(HValue::kLeftCanBeNegative) && |
| 1383 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1262 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1384 result = AssignEnvironment(result); | 1263 result = AssignEnvironment(result); |
| 1385 } | 1264 } |
| 1386 return result; | 1265 return result; |
| 1387 } | 1266 } |
| 1388 | 1267 |
| 1389 | |
| 1390 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) { | 1268 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) { |
| 1391 DCHECK(instr->representation().IsSmiOrInteger32()); | 1269 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1392 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1270 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1393 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1271 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1394 LOperand* dividend = UseRegister(instr->left()); | 1272 LOperand* dividend = UseRegister(instr->left()); |
| 1395 int32_t divisor = instr->right()->GetInteger32Constant(); | 1273 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1396 LInstruction* result = | 1274 LInstruction* result = |
| 1397 DefineAsRegister(new (zone()) LModByConstI(dividend, divisor)); | 1275 DefineAsRegister(new (zone()) LModByConstI(dividend, divisor)); |
| 1398 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1276 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1399 result = AssignEnvironment(result); | 1277 result = AssignEnvironment(result); |
| 1400 } | 1278 } |
| 1401 return result; | 1279 return result; |
| 1402 } | 1280 } |
| 1403 | 1281 |
| 1404 | |
| 1405 LInstruction* LChunkBuilder::DoModI(HMod* instr) { | 1282 LInstruction* LChunkBuilder::DoModI(HMod* instr) { |
| 1406 DCHECK(instr->representation().IsSmiOrInteger32()); | 1283 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1407 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1284 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1408 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1285 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1409 LOperand* dividend = UseRegister(instr->left()); | 1286 LOperand* dividend = UseRegister(instr->left()); |
| 1410 LOperand* divisor = UseRegister(instr->right()); | 1287 LOperand* divisor = UseRegister(instr->right()); |
| 1411 LInstruction* result = | 1288 LInstruction* result = |
| 1412 DefineAsRegister(new (zone()) LModI(dividend, divisor)); | 1289 DefineAsRegister(new (zone()) LModI(dividend, divisor)); |
| 1413 if (instr->CheckFlag(HValue::kCanBeDivByZero) || | 1290 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1414 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1291 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1415 result = AssignEnvironment(result); | 1292 result = AssignEnvironment(result); |
| 1416 } | 1293 } |
| 1417 return result; | 1294 return result; |
| 1418 } | 1295 } |
| 1419 | 1296 |
| 1420 | |
| 1421 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1297 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1422 if (instr->representation().IsSmiOrInteger32()) { | 1298 if (instr->representation().IsSmiOrInteger32()) { |
| 1423 if (instr->RightIsPowerOf2()) { | 1299 if (instr->RightIsPowerOf2()) { |
| 1424 return DoModByPowerOf2I(instr); | 1300 return DoModByPowerOf2I(instr); |
| 1425 } else if (instr->right()->IsConstant()) { | 1301 } else if (instr->right()->IsConstant()) { |
| 1426 return DoModByConstI(instr); | 1302 return DoModByConstI(instr); |
| 1427 } else { | 1303 } else { |
| 1428 return DoModI(instr); | 1304 return DoModI(instr); |
| 1429 } | 1305 } |
| 1430 } else if (instr->representation().IsDouble()) { | 1306 } else if (instr->representation().IsDouble()) { |
| 1431 return DoArithmeticD(Token::MOD, instr); | 1307 return DoArithmeticD(Token::MOD, instr); |
| 1432 } else { | 1308 } else { |
| 1433 return DoArithmeticT(Token::MOD, instr); | 1309 return DoArithmeticT(Token::MOD, instr); |
| 1434 } | 1310 } |
| 1435 } | 1311 } |
| 1436 | 1312 |
| 1437 | |
| 1438 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1313 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1439 if (instr->representation().IsSmiOrInteger32()) { | 1314 if (instr->representation().IsSmiOrInteger32()) { |
| 1440 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1315 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1441 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1316 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1442 HValue* left = instr->BetterLeftOperand(); | 1317 HValue* left = instr->BetterLeftOperand(); |
| 1443 HValue* right = instr->BetterRightOperand(); | 1318 HValue* right = instr->BetterRightOperand(); |
| 1444 LOperand* left_op; | 1319 LOperand* left_op; |
| 1445 LOperand* right_op; | 1320 LOperand* right_op; |
| 1446 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); | 1321 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); |
| 1447 bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero); | 1322 bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1480 } | 1355 } |
| 1481 return DefineAsRegister(mul); | 1356 return DefineAsRegister(mul); |
| 1482 | 1357 |
| 1483 } else if (instr->representation().IsDouble()) { | 1358 } else if (instr->representation().IsDouble()) { |
| 1484 return DoArithmeticD(Token::MUL, instr); | 1359 return DoArithmeticD(Token::MUL, instr); |
| 1485 } else { | 1360 } else { |
| 1486 return DoArithmeticT(Token::MUL, instr); | 1361 return DoArithmeticT(Token::MUL, instr); |
| 1487 } | 1362 } |
| 1488 } | 1363 } |
| 1489 | 1364 |
| 1490 | |
| 1491 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1365 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
| 1492 if (instr->representation().IsSmiOrInteger32()) { | 1366 if (instr->representation().IsSmiOrInteger32()) { |
| 1493 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1367 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1494 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1368 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1495 | 1369 |
| 1496 if (instr->left()->IsConstant() && | 1370 if (instr->left()->IsConstant() && |
| 1497 !instr->CheckFlag(HValue::kCanOverflow)) { | 1371 !instr->CheckFlag(HValue::kCanOverflow)) { |
| 1498 // If lhs is constant, do reverse subtraction instead. | 1372 // If lhs is constant, do reverse subtraction instead. |
| 1499 return DoRSub(instr); | 1373 return DoRSub(instr); |
| 1500 } | 1374 } |
| 1501 | 1375 |
| 1502 LOperand* left = UseRegisterAtStart(instr->left()); | 1376 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1503 LOperand* right = UseOrConstantAtStart(instr->right()); | 1377 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1504 LSubI* sub = new (zone()) LSubI(left, right); | 1378 LSubI* sub = new (zone()) LSubI(left, right); |
| 1505 LInstruction* result = DefineAsRegister(sub); | 1379 LInstruction* result = DefineAsRegister(sub); |
| 1506 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1380 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1507 result = AssignEnvironment(result); | 1381 result = AssignEnvironment(result); |
| 1508 } | 1382 } |
| 1509 return result; | 1383 return result; |
| 1510 } else if (instr->representation().IsDouble()) { | 1384 } else if (instr->representation().IsDouble()) { |
| 1511 return DoArithmeticD(Token::SUB, instr); | 1385 return DoArithmeticD(Token::SUB, instr); |
| 1512 } else { | 1386 } else { |
| 1513 return DoArithmeticT(Token::SUB, instr); | 1387 return DoArithmeticT(Token::SUB, instr); |
| 1514 } | 1388 } |
| 1515 } | 1389 } |
| 1516 | 1390 |
| 1517 | |
| 1518 LInstruction* LChunkBuilder::DoRSub(HSub* instr) { | 1391 LInstruction* LChunkBuilder::DoRSub(HSub* instr) { |
| 1519 DCHECK(instr->representation().IsSmiOrInteger32()); | 1392 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1520 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1393 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1521 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1394 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1522 DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); | 1395 DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); |
| 1523 | 1396 |
| 1524 // Note: The lhs of the subtraction becomes the rhs of the | 1397 // Note: The lhs of the subtraction becomes the rhs of the |
| 1525 // reverse-subtraction. | 1398 // reverse-subtraction. |
| 1526 LOperand* left = UseRegisterAtStart(instr->right()); | 1399 LOperand* left = UseRegisterAtStart(instr->right()); |
| 1527 LOperand* right = UseOrConstantAtStart(instr->left()); | 1400 LOperand* right = UseOrConstantAtStart(instr->left()); |
| 1528 LRSubI* rsb = new (zone()) LRSubI(left, right); | 1401 LRSubI* rsb = new (zone()) LRSubI(left, right); |
| 1529 LInstruction* result = DefineAsRegister(rsb); | 1402 LInstruction* result = DefineAsRegister(rsb); |
| 1530 return result; | 1403 return result; |
| 1531 } | 1404 } |
| 1532 | 1405 |
| 1533 | |
| 1534 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) { | 1406 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) { |
| 1535 LOperand* multiplier_op = UseRegisterAtStart(mul->left()); | 1407 LOperand* multiplier_op = UseRegister(mul->left()); |
| 1536 LOperand* multiplicand_op = UseRegisterAtStart(mul->right()); | 1408 LOperand* multiplicand_op = UseRegister(mul->right()); |
| 1537 LOperand* addend_op = UseRegisterAtStart(addend); | 1409 LOperand* addend_op = UseRegister(addend); |
| 1538 return DefineSameAsFirst( | 1410 return DefineAsRegister( |
| 1539 new (zone()) LMultiplyAddD(addend_op, multiplier_op, multiplicand_op)); | 1411 new (zone()) LMultiplyAddD(addend_op, multiplier_op, multiplicand_op)); |
| 1540 } | 1412 } |
| 1541 | 1413 |
| 1414 LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) { |
| 1415 LOperand* minuend_op = UseRegister(minuend); |
| 1416 LOperand* multiplier_op = UseRegister(mul->left()); |
| 1417 LOperand* multiplicand_op = UseRegister(mul->right()); |
| 1542 | 1418 |
| 1543 LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) { | 1419 return DefineAsRegister( |
| 1544 LOperand* minuend_op = UseRegisterAtStart(minuend); | |
| 1545 LOperand* multiplier_op = UseRegisterAtStart(mul->left()); | |
| 1546 LOperand* multiplicand_op = UseRegisterAtStart(mul->right()); | |
| 1547 | |
| 1548 return DefineSameAsFirst( | |
| 1549 new (zone()) LMultiplySubD(minuend_op, multiplier_op, multiplicand_op)); | 1420 new (zone()) LMultiplySubD(minuend_op, multiplier_op, multiplicand_op)); |
| 1550 } | 1421 } |
| 1551 | 1422 |
| 1552 | |
| 1553 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { | 1423 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { |
| 1554 if (instr->representation().IsSmiOrInteger32()) { | 1424 if (instr->representation().IsSmiOrInteger32()) { |
| 1555 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1425 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1556 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1426 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1557 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1427 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1558 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1428 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1559 LAddI* add = new (zone()) LAddI(left, right); | 1429 LAddI* add = new (zone()) LAddI(left, right); |
| 1560 LInstruction* result = DefineAsRegister(add); | 1430 LInstruction* result = DefineAsRegister(add); |
| 1561 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1431 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1562 result = AssignEnvironment(result); | 1432 result = AssignEnvironment(result); |
| 1563 } | 1433 } |
| 1564 return result; | 1434 return result; |
| 1565 } else if (instr->representation().IsExternal()) { | 1435 } else if (instr->representation().IsExternal()) { |
| 1566 DCHECK(instr->IsConsistentExternalRepresentation()); | 1436 DCHECK(instr->IsConsistentExternalRepresentation()); |
| 1567 DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); | 1437 DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); |
| 1568 LOperand* left = UseRegisterAtStart(instr->left()); | 1438 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1569 LOperand* right = UseOrConstantAtStart(instr->right()); | 1439 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1570 LAddI* add = new (zone()) LAddI(left, right); | 1440 LAddI* add = new (zone()) LAddI(left, right); |
| 1571 LInstruction* result = DefineAsRegister(add); | 1441 LInstruction* result = DefineAsRegister(add); |
| 1572 return result; | 1442 return result; |
| 1573 } else if (instr->representation().IsDouble()) { | 1443 } else if (instr->representation().IsDouble()) { |
| 1574 return DoArithmeticD(Token::ADD, instr); | 1444 return DoArithmeticD(Token::ADD, instr); |
| 1575 } else { | 1445 } else { |
| 1576 return DoArithmeticT(Token::ADD, instr); | 1446 return DoArithmeticT(Token::ADD, instr); |
| 1577 } | 1447 } |
| 1578 } | 1448 } |
| 1579 | 1449 |
| 1580 | |
| 1581 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1450 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
| 1582 LOperand* left = NULL; | 1451 LOperand* left = NULL; |
| 1583 LOperand* right = NULL; | 1452 LOperand* right = NULL; |
| 1584 if (instr->representation().IsSmiOrInteger32()) { | 1453 if (instr->representation().IsSmiOrInteger32()) { |
| 1585 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1454 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1586 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1455 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1587 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1456 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1588 right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1457 right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1589 } else { | 1458 } else { |
| 1590 DCHECK(instr->representation().IsDouble()); | 1459 DCHECK(instr->representation().IsDouble()); |
| 1591 DCHECK(instr->left()->representation().IsDouble()); | 1460 DCHECK(instr->left()->representation().IsDouble()); |
| 1592 DCHECK(instr->right()->representation().IsDouble()); | 1461 DCHECK(instr->right()->representation().IsDouble()); |
| 1593 left = UseRegisterAtStart(instr->left()); | 1462 left = UseRegister(instr->left()); |
| 1594 right = UseRegisterAtStart(instr->right()); | 1463 right = UseRegister(instr->right()); |
| 1595 } | 1464 } |
| 1596 return DefineAsRegister(new (zone()) LMathMinMax(left, right)); | 1465 return DefineAsRegister(new (zone()) LMathMinMax(left, right)); |
| 1597 } | 1466 } |
| 1598 | 1467 |
| 1599 | |
| 1600 LInstruction* LChunkBuilder::DoPower(HPower* instr) { | 1468 LInstruction* LChunkBuilder::DoPower(HPower* instr) { |
| 1601 DCHECK(instr->representation().IsDouble()); | 1469 DCHECK(instr->representation().IsDouble()); |
| 1602 // We call a C function for double power. It can't trigger a GC. | 1470 // We call a C function for double power. It can't trigger a GC. |
| 1603 // We need to use fixed result register for the call. | 1471 // We need to use fixed result register for the call. |
| 1604 Representation exponent_type = instr->right()->representation(); | 1472 Representation exponent_type = instr->right()->representation(); |
| 1605 DCHECK(instr->left()->representation().IsDouble()); | 1473 DCHECK(instr->left()->representation().IsDouble()); |
| 1606 LOperand* left = UseFixedDouble(instr->left(), d1); | 1474 LOperand* left = UseFixedDouble(instr->left(), d1); |
| 1607 LOperand* right = | 1475 LOperand* right = exponent_type.IsDouble() |
| 1608 exponent_type.IsDouble() | 1476 ? UseFixedDouble(instr->right(), d2) |
| 1609 ? UseFixedDouble(instr->right(), d2) | 1477 : UseFixed(instr->right(), r4); |
| 1610 : UseFixed(instr->right(), MathPowTaggedDescriptor::exponent()); | |
| 1611 LPower* result = new (zone()) LPower(left, right); | 1478 LPower* result = new (zone()) LPower(left, right); |
| 1612 return MarkAsCall(DefineFixedDouble(result, d3), instr, | 1479 return MarkAsCall(DefineFixedDouble(result, d3), instr, |
| 1613 CAN_DEOPTIMIZE_EAGERLY); | 1480 CAN_DEOPTIMIZE_EAGERLY); |
| 1614 } | 1481 } |
| 1615 | 1482 |
| 1616 | |
| 1617 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { | 1483 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { |
| 1618 DCHECK(instr->left()->representation().IsTagged()); | 1484 DCHECK(instr->left()->representation().IsTagged()); |
| 1619 DCHECK(instr->right()->representation().IsTagged()); | 1485 DCHECK(instr->right()->representation().IsTagged()); |
| 1620 LOperand* context = UseFixed(instr->context(), cp); | 1486 LOperand* context = UseFixed(instr->context(), cp); |
| 1621 LOperand* left = UseFixed(instr->left(), r4); | 1487 LOperand* left = UseFixed(instr->left(), r3); |
| 1622 LOperand* right = UseFixed(instr->right(), r3); | 1488 LOperand* right = UseFixed(instr->right(), r2); |
| 1623 LCmpT* result = new (zone()) LCmpT(context, left, right); | 1489 LCmpT* result = new (zone()) LCmpT(context, left, right); |
| 1624 return MarkAsCall(DefineFixed(result, r3), instr); | 1490 return MarkAsCall(DefineFixed(result, r2), instr); |
| 1625 } | 1491 } |
| 1626 | 1492 |
| 1627 | |
| 1628 LInstruction* LChunkBuilder::DoCompareNumericAndBranch( | 1493 LInstruction* LChunkBuilder::DoCompareNumericAndBranch( |
| 1629 HCompareNumericAndBranch* instr) { | 1494 HCompareNumericAndBranch* instr) { |
| 1630 Representation r = instr->representation(); | 1495 Representation r = instr->representation(); |
| 1631 if (r.IsSmiOrInteger32()) { | 1496 if (r.IsSmiOrInteger32()) { |
| 1632 DCHECK(instr->left()->representation().Equals(r)); | 1497 DCHECK(instr->left()->representation().Equals(r)); |
| 1633 DCHECK(instr->right()->representation().Equals(r)); | 1498 DCHECK(instr->right()->representation().Equals(r)); |
| 1634 LOperand* left = UseRegisterOrConstantAtStart(instr->left()); | 1499 LOperand* left = UseRegisterOrConstantAtStart(instr->left()); |
| 1635 LOperand* right = UseRegisterOrConstantAtStart(instr->right()); | 1500 LOperand* right = UseRegisterOrConstantAtStart(instr->right()); |
| 1636 return new (zone()) LCompareNumericAndBranch(left, right); | 1501 return new (zone()) LCompareNumericAndBranch(left, right); |
| 1637 } else { | 1502 } else { |
| 1638 DCHECK(r.IsDouble()); | 1503 DCHECK(r.IsDouble()); |
| 1639 DCHECK(instr->left()->representation().IsDouble()); | 1504 DCHECK(instr->left()->representation().IsDouble()); |
| 1640 DCHECK(instr->right()->representation().IsDouble()); | 1505 DCHECK(instr->right()->representation().IsDouble()); |
| 1641 LOperand* left = UseRegisterAtStart(instr->left()); | 1506 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1642 LOperand* right = UseRegisterAtStart(instr->right()); | 1507 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1643 return new (zone()) LCompareNumericAndBranch(left, right); | 1508 return new (zone()) LCompareNumericAndBranch(left, right); |
| 1644 } | 1509 } |
| 1645 } | 1510 } |
| 1646 | 1511 |
| 1647 | |
| 1648 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( | 1512 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
| 1649 HCompareObjectEqAndBranch* instr) { | 1513 HCompareObjectEqAndBranch* instr) { |
| 1650 LOperand* left = UseRegisterAtStart(instr->left()); | 1514 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1651 LOperand* right = UseRegisterAtStart(instr->right()); | 1515 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1652 return new (zone()) LCmpObjectEqAndBranch(left, right); | 1516 return new (zone()) LCmpObjectEqAndBranch(left, right); |
| 1653 } | 1517 } |
| 1654 | 1518 |
| 1655 | |
| 1656 LInstruction* LChunkBuilder::DoCompareHoleAndBranch( | 1519 LInstruction* LChunkBuilder::DoCompareHoleAndBranch( |
| 1657 HCompareHoleAndBranch* instr) { | 1520 HCompareHoleAndBranch* instr) { |
| 1658 LOperand* value = UseRegisterAtStart(instr->value()); | 1521 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1659 return new (zone()) LCmpHoleAndBranch(value); | 1522 return new (zone()) LCmpHoleAndBranch(value); |
| 1660 } | 1523 } |
| 1661 | 1524 |
| 1662 | |
| 1663 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { | 1525 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { |
| 1664 DCHECK(instr->value()->representation().IsTagged()); | 1526 DCHECK(instr->value()->representation().IsTagged()); |
| 1665 LOperand* value = UseRegisterAtStart(instr->value()); | 1527 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1666 LOperand* temp = TempRegister(); | 1528 LOperand* temp = TempRegister(); |
| 1667 return new (zone()) LIsStringAndBranch(value, temp); | 1529 return new (zone()) LIsStringAndBranch(value, temp); |
| 1668 } | 1530 } |
| 1669 | 1531 |
| 1670 | |
| 1671 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { | 1532 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { |
| 1672 DCHECK(instr->value()->representation().IsTagged()); | 1533 DCHECK(instr->value()->representation().IsTagged()); |
| 1673 return new (zone()) LIsSmiAndBranch(Use(instr->value())); | 1534 return new (zone()) LIsSmiAndBranch(Use(instr->value())); |
| 1674 } | 1535 } |
| 1675 | 1536 |
| 1676 | |
| 1677 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( | 1537 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( |
| 1678 HIsUndetectableAndBranch* instr) { | 1538 HIsUndetectableAndBranch* instr) { |
| 1679 DCHECK(instr->value()->representation().IsTagged()); | 1539 DCHECK(instr->value()->representation().IsTagged()); |
| 1680 LOperand* value = UseRegisterAtStart(instr->value()); | 1540 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1681 return new (zone()) LIsUndetectableAndBranch(value, TempRegister()); | 1541 return new (zone()) LIsUndetectableAndBranch(value, TempRegister()); |
| 1682 } | 1542 } |
| 1683 | 1543 |
| 1684 | |
| 1685 LInstruction* LChunkBuilder::DoStringCompareAndBranch( | 1544 LInstruction* LChunkBuilder::DoStringCompareAndBranch( |
| 1686 HStringCompareAndBranch* instr) { | 1545 HStringCompareAndBranch* instr) { |
| 1687 DCHECK(instr->left()->representation().IsTagged()); | 1546 DCHECK(instr->left()->representation().IsTagged()); |
| 1688 DCHECK(instr->right()->representation().IsTagged()); | 1547 DCHECK(instr->right()->representation().IsTagged()); |
| 1689 LOperand* context = UseFixed(instr->context(), cp); | 1548 LOperand* context = UseFixed(instr->context(), cp); |
| 1690 LOperand* left = UseFixed(instr->left(), r4); | 1549 LOperand* left = UseFixed(instr->left(), r3); |
| 1691 LOperand* right = UseFixed(instr->right(), r3); | 1550 LOperand* right = UseFixed(instr->right(), r2); |
| 1692 LStringCompareAndBranch* result = | 1551 LStringCompareAndBranch* result = |
| 1693 new (zone()) LStringCompareAndBranch(context, left, right); | 1552 new (zone()) LStringCompareAndBranch(context, left, right); |
| 1694 return MarkAsCall(result, instr); | 1553 return MarkAsCall(result, instr); |
| 1695 } | 1554 } |
| 1696 | 1555 |
| 1697 | |
| 1698 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( | 1556 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( |
| 1699 HHasInstanceTypeAndBranch* instr) { | 1557 HHasInstanceTypeAndBranch* instr) { |
| 1700 DCHECK(instr->value()->representation().IsTagged()); | 1558 DCHECK(instr->value()->representation().IsTagged()); |
| 1701 LOperand* value = UseRegisterAtStart(instr->value()); | 1559 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1702 return new (zone()) LHasInstanceTypeAndBranch(value); | 1560 return new (zone()) LHasInstanceTypeAndBranch(value); |
| 1703 } | 1561 } |
| 1704 | 1562 |
| 1705 | |
| 1706 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( | 1563 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( |
| 1707 HGetCachedArrayIndex* instr) { | 1564 HGetCachedArrayIndex* instr) { |
| 1708 DCHECK(instr->value()->representation().IsTagged()); | 1565 DCHECK(instr->value()->representation().IsTagged()); |
| 1709 LOperand* value = UseRegisterAtStart(instr->value()); | 1566 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1710 | 1567 |
| 1711 return DefineAsRegister(new (zone()) LGetCachedArrayIndex(value)); | 1568 return DefineAsRegister(new (zone()) LGetCachedArrayIndex(value)); |
| 1712 } | 1569 } |
| 1713 | 1570 |
| 1714 | |
| 1715 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( | 1571 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( |
| 1716 HHasCachedArrayIndexAndBranch* instr) { | 1572 HHasCachedArrayIndexAndBranch* instr) { |
| 1717 DCHECK(instr->value()->representation().IsTagged()); | 1573 DCHECK(instr->value()->representation().IsTagged()); |
| 1718 return new (zone()) | 1574 return new (zone()) |
| 1719 LHasCachedArrayIndexAndBranch(UseRegisterAtStart(instr->value())); | 1575 LHasCachedArrayIndexAndBranch(UseRegisterAtStart(instr->value())); |
| 1720 } | 1576 } |
| 1721 | 1577 |
| 1722 | |
| 1723 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( | 1578 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( |
| 1724 HClassOfTestAndBranch* instr) { | 1579 HClassOfTestAndBranch* instr) { |
| 1725 DCHECK(instr->value()->representation().IsTagged()); | 1580 DCHECK(instr->value()->representation().IsTagged()); |
| 1726 LOperand* value = UseRegister(instr->value()); | 1581 LOperand* value = UseRegister(instr->value()); |
| 1727 return new (zone()) LClassOfTestAndBranch(value, TempRegister()); | 1582 return new (zone()) LClassOfTestAndBranch(value, TempRegister()); |
| 1728 } | 1583 } |
| 1729 | 1584 |
| 1730 | |
| 1731 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { | 1585 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { |
| 1732 LOperand* string = UseRegisterAtStart(instr->string()); | 1586 LOperand* string = UseRegisterAtStart(instr->string()); |
| 1733 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); | 1587 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); |
| 1734 return DefineAsRegister(new (zone()) LSeqStringGetChar(string, index)); | 1588 return DefineAsRegister(new (zone()) LSeqStringGetChar(string, index)); |
| 1735 } | 1589 } |
| 1736 | 1590 |
| 1737 | |
| 1738 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { | 1591 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { |
| 1739 LOperand* string = UseRegisterAtStart(instr->string()); | 1592 LOperand* string = UseRegisterAtStart(instr->string()); |
| 1740 LOperand* index = FLAG_debug_code | 1593 LOperand* index = FLAG_debug_code |
| 1741 ? UseRegisterAtStart(instr->index()) | 1594 ? UseRegisterAtStart(instr->index()) |
| 1742 : UseRegisterOrConstantAtStart(instr->index()); | 1595 : UseRegisterOrConstantAtStart(instr->index()); |
| 1743 LOperand* value = UseRegisterAtStart(instr->value()); | 1596 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1744 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL; | 1597 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL; |
| 1745 return new (zone()) LSeqStringSetChar(context, string, index, value); | 1598 return new (zone()) LSeqStringSetChar(context, string, index, value); |
| 1746 } | 1599 } |
| 1747 | 1600 |
| 1748 | |
| 1749 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1601 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
| 1750 if (!FLAG_debug_code && instr->skip_check()) return NULL; | 1602 if (!FLAG_debug_code && instr->skip_check()) return NULL; |
| 1751 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); | 1603 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); |
| 1752 LOperand* length = !index->IsConstantOperand() | 1604 LOperand* length = !index->IsConstantOperand() |
| 1753 ? UseRegisterOrConstantAtStart(instr->length()) | 1605 ? UseRegisterOrConstantAtStart(instr->length()) |
| 1754 : UseRegisterAtStart(instr->length()); | 1606 : UseRegisterAtStart(instr->length()); |
| 1755 LInstruction* result = new (zone()) LBoundsCheck(index, length); | 1607 LInstruction* result = new (zone()) LBoundsCheck(index, length); |
| 1756 if (!FLAG_debug_code || !instr->skip_check()) { | 1608 if (!FLAG_debug_code || !instr->skip_check()) { |
| 1757 result = AssignEnvironment(result); | 1609 result = AssignEnvironment(result); |
| 1758 } | 1610 } |
| 1759 return result; | 1611 return result; |
| 1760 } | 1612 } |
| 1761 | 1613 |
| 1762 | |
| 1763 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation( | 1614 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation( |
| 1764 HBoundsCheckBaseIndexInformation* instr) { | 1615 HBoundsCheckBaseIndexInformation* instr) { |
| 1765 UNREACHABLE(); | 1616 UNREACHABLE(); |
| 1766 return NULL; | 1617 return NULL; |
| 1767 } | 1618 } |
| 1768 | 1619 |
| 1769 | |
| 1770 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { | 1620 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
| 1771 // The control instruction marking the end of a block that completed | 1621 // The control instruction marking the end of a block that completed |
| 1772 // abruptly (e.g., threw an exception). There is nothing specific to do. | 1622 // abruptly (e.g., threw an exception). There is nothing specific to do. |
| 1773 return NULL; | 1623 return NULL; |
| 1774 } | 1624 } |
| 1775 | 1625 |
| 1776 | |
| 1777 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { return NULL; } | 1626 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { return NULL; } |
| 1778 | 1627 |
| 1779 | |
| 1780 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { | 1628 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { |
| 1781 // All HForceRepresentation instructions should be eliminated in the | 1629 // All HForceRepresentation instructions should be eliminated in the |
| 1782 // representation change phase of Hydrogen. | 1630 // representation change phase of Hydrogen. |
| 1783 UNREACHABLE(); | 1631 UNREACHABLE(); |
| 1784 return NULL; | 1632 return NULL; |
| 1785 } | 1633 } |
| 1786 | 1634 |
| 1787 | |
| 1788 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1635 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
| 1789 Representation from = instr->from(); | 1636 Representation from = instr->from(); |
| 1790 Representation to = instr->to(); | 1637 Representation to = instr->to(); |
| 1791 HValue* val = instr->value(); | 1638 HValue* val = instr->value(); |
| 1792 if (from.IsSmi()) { | 1639 if (from.IsSmi()) { |
| 1793 if (to.IsTagged()) { | 1640 if (to.IsTagged()) { |
| 1794 LOperand* value = UseRegister(val); | 1641 LOperand* value = UseRegister(val); |
| 1795 return DefineSameAsFirst(new (zone()) LDummyUse(value)); | 1642 return DefineSameAsFirst(new (zone()) LDummyUse(value)); |
| 1796 } | 1643 } |
| 1797 from = Representation::Tagged(); | 1644 from = Representation::Tagged(); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1877 return DefineAsRegister(new (zone()) LUint32ToDouble(UseRegister(val))); | 1724 return DefineAsRegister(new (zone()) LUint32ToDouble(UseRegister(val))); |
| 1878 } else { | 1725 } else { |
| 1879 return DefineAsRegister(new (zone()) LInteger32ToDouble(Use(val))); | 1726 return DefineAsRegister(new (zone()) LInteger32ToDouble(Use(val))); |
| 1880 } | 1727 } |
| 1881 } | 1728 } |
| 1882 } | 1729 } |
| 1883 UNREACHABLE(); | 1730 UNREACHABLE(); |
| 1884 return NULL; | 1731 return NULL; |
| 1885 } | 1732 } |
| 1886 | 1733 |
| 1887 | |
| 1888 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { | 1734 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { |
| 1889 LOperand* value = UseRegisterAtStart(instr->value()); | 1735 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1890 LInstruction* result = new (zone()) LCheckNonSmi(value); | 1736 LInstruction* result = new (zone()) LCheckNonSmi(value); |
| 1891 if (!instr->value()->type().IsHeapObject()) { | 1737 if (!instr->value()->type().IsHeapObject()) { |
| 1892 result = AssignEnvironment(result); | 1738 result = AssignEnvironment(result); |
| 1893 } | 1739 } |
| 1894 return result; | 1740 return result; |
| 1895 } | 1741 } |
| 1896 | 1742 |
| 1897 | |
| 1898 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { | 1743 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { |
| 1899 LOperand* value = UseRegisterAtStart(instr->value()); | 1744 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1900 return AssignEnvironment(new (zone()) LCheckSmi(value)); | 1745 return AssignEnvironment(new (zone()) LCheckSmi(value)); |
| 1901 } | 1746 } |
| 1902 | 1747 |
| 1903 | |
| 1904 LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered( | 1748 LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered( |
| 1905 HCheckArrayBufferNotNeutered* instr) { | 1749 HCheckArrayBufferNotNeutered* instr) { |
| 1906 LOperand* view = UseRegisterAtStart(instr->value()); | 1750 LOperand* view = UseRegisterAtStart(instr->value()); |
| 1907 LCheckArrayBufferNotNeutered* result = | 1751 LCheckArrayBufferNotNeutered* result = |
| 1908 new (zone()) LCheckArrayBufferNotNeutered(view); | 1752 new (zone()) LCheckArrayBufferNotNeutered(view); |
| 1909 return AssignEnvironment(result); | 1753 return AssignEnvironment(result); |
| 1910 } | 1754 } |
| 1911 | 1755 |
| 1912 | |
| 1913 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 1756 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
| 1914 LOperand* value = UseRegisterAtStart(instr->value()); | 1757 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1915 LInstruction* result = new (zone()) LCheckInstanceType(value); | 1758 LInstruction* result = new (zone()) LCheckInstanceType(value); |
| 1916 return AssignEnvironment(result); | 1759 return AssignEnvironment(result); |
| 1917 } | 1760 } |
| 1918 | 1761 |
| 1919 | |
| 1920 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { | 1762 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { |
| 1921 LOperand* value = UseRegisterAtStart(instr->value()); | 1763 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1922 return AssignEnvironment(new (zone()) LCheckValue(value)); | 1764 return AssignEnvironment(new (zone()) LCheckValue(value)); |
| 1923 } | 1765 } |
| 1924 | 1766 |
| 1925 | |
| 1926 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { | 1767 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { |
| 1927 if (instr->IsStabilityCheck()) return new (zone()) LCheckMaps; | 1768 if (instr->IsStabilityCheck()) return new (zone()) LCheckMaps; |
| 1928 LOperand* value = UseRegisterAtStart(instr->value()); | 1769 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1929 LOperand* temp = TempRegister(); | 1770 LOperand* temp = TempRegister(); |
| 1930 LInstruction* result = | 1771 LInstruction* result = |
| 1931 AssignEnvironment(new (zone()) LCheckMaps(value, temp)); | 1772 AssignEnvironment(new (zone()) LCheckMaps(value, temp)); |
| 1932 if (instr->HasMigrationTarget()) { | 1773 if (instr->HasMigrationTarget()) { |
| 1933 info()->MarkAsDeferredCalling(); | 1774 info()->MarkAsDeferredCalling(); |
| 1934 result = AssignPointerMap(result); | 1775 result = AssignPointerMap(result); |
| 1935 } | 1776 } |
| 1936 return result; | 1777 return result; |
| 1937 } | 1778 } |
| 1938 | 1779 |
| 1939 | |
| 1940 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { | 1780 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
| 1941 HValue* value = instr->value(); | 1781 HValue* value = instr->value(); |
| 1942 Representation input_rep = value->representation(); | 1782 Representation input_rep = value->representation(); |
| 1943 LOperand* reg = UseRegister(value); | 1783 LOperand* reg = UseRegister(value); |
| 1944 if (input_rep.IsDouble()) { | 1784 if (input_rep.IsDouble()) { |
| 1945 return DefineAsRegister(new (zone()) LClampDToUint8(reg)); | 1785 return DefineAsRegister(new (zone()) LClampDToUint8(reg)); |
| 1946 } else if (input_rep.IsInteger32()) { | 1786 } else if (input_rep.IsInteger32()) { |
| 1947 return DefineAsRegister(new (zone()) LClampIToUint8(reg)); | 1787 return DefineAsRegister(new (zone()) LClampIToUint8(reg)); |
| 1948 } else { | 1788 } else { |
| 1949 DCHECK(input_rep.IsSmiOrTagged()); | 1789 DCHECK(input_rep.IsSmiOrTagged()); |
| 1950 LClampTToUint8* result = | 1790 LClampTToUint8* result = |
| 1951 new (zone()) LClampTToUint8(reg, TempDoubleRegister()); | 1791 new (zone()) LClampTToUint8(reg, TempDoubleRegister()); |
| 1952 return AssignEnvironment(DefineAsRegister(result)); | 1792 return AssignEnvironment(DefineAsRegister(result)); |
| 1953 } | 1793 } |
| 1954 } | 1794 } |
| 1955 | 1795 |
| 1956 | |
| 1957 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) { | 1796 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) { |
| 1958 HValue* value = instr->value(); | 1797 HValue* value = instr->value(); |
| 1959 DCHECK(value->representation().IsDouble()); | 1798 DCHECK(value->representation().IsDouble()); |
| 1960 return DefineAsRegister(new (zone()) LDoubleBits(UseRegister(value))); | 1799 return DefineAsRegister(new (zone()) LDoubleBits(UseRegister(value))); |
| 1961 } | 1800 } |
| 1962 | 1801 |
| 1963 | |
| 1964 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) { | 1802 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) { |
| 1965 LOperand* lo = UseRegister(instr->lo()); | 1803 LOperand* lo = UseRegister(instr->lo()); |
| 1966 LOperand* hi = UseRegister(instr->hi()); | 1804 LOperand* hi = UseRegister(instr->hi()); |
| 1967 return DefineAsRegister(new (zone()) LConstructDouble(hi, lo)); | 1805 return DefineAsRegister(new (zone()) LConstructDouble(hi, lo)); |
| 1968 } | 1806 } |
| 1969 | 1807 |
| 1970 | |
| 1971 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 1808 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
| 1972 LOperand* context = info()->IsStub() ? UseFixed(instr->context(), cp) : NULL; | 1809 LOperand* context = info()->IsStub() ? UseFixed(instr->context(), cp) : NULL; |
| 1973 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); | 1810 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); |
| 1974 return new (zone()) | 1811 return new (zone()) |
| 1975 LReturn(UseFixed(instr->value(), r3), context, parameter_count); | 1812 LReturn(UseFixed(instr->value(), r2), context, parameter_count); |
| 1976 } | 1813 } |
| 1977 | 1814 |
| 1978 | |
| 1979 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { | 1815 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
| 1980 Representation r = instr->representation(); | 1816 Representation r = instr->representation(); |
| 1981 if (r.IsSmi()) { | 1817 if (r.IsSmi()) { |
| 1982 return DefineAsRegister(new (zone()) LConstantS); | 1818 return DefineAsRegister(new (zone()) LConstantS); |
| 1983 } else if (r.IsInteger32()) { | 1819 } else if (r.IsInteger32()) { |
| 1984 return DefineAsRegister(new (zone()) LConstantI); | 1820 return DefineAsRegister(new (zone()) LConstantI); |
| 1985 } else if (r.IsDouble()) { | 1821 } else if (r.IsDouble()) { |
| 1986 return DefineAsRegister(new (zone()) LConstantD); | 1822 return DefineAsRegister(new (zone()) LConstantD); |
| 1987 } else if (r.IsExternal()) { | 1823 } else if (r.IsExternal()) { |
| 1988 return DefineAsRegister(new (zone()) LConstantE); | 1824 return DefineAsRegister(new (zone()) LConstantE); |
| 1989 } else if (r.IsTagged()) { | 1825 } else if (r.IsTagged()) { |
| 1990 return DefineAsRegister(new (zone()) LConstantT); | 1826 return DefineAsRegister(new (zone()) LConstantT); |
| 1991 } else { | 1827 } else { |
| 1992 UNREACHABLE(); | 1828 UNREACHABLE(); |
| 1993 return NULL; | 1829 return NULL; |
| 1994 } | 1830 } |
| 1995 } | 1831 } |
| 1996 | 1832 |
| 1997 | |
| 1998 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { | 1833 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { |
| 1999 LOperand* context = UseFixed(instr->context(), cp); | 1834 LOperand* context = UseFixed(instr->context(), cp); |
| 2000 LOperand* global_object = | 1835 LOperand* global_object = |
| 2001 UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister()); | 1836 UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister()); |
| 2002 LOperand* vector = NULL; | 1837 LOperand* vector = NULL; |
| 2003 if (instr->HasVectorAndSlot()) { | 1838 if (instr->HasVectorAndSlot()) { |
| 2004 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); | 1839 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); |
| 2005 } | 1840 } |
| 2006 LLoadGlobalGeneric* result = | 1841 LLoadGlobalGeneric* result = |
| 2007 new (zone()) LLoadGlobalGeneric(context, global_object, vector); | 1842 new (zone()) LLoadGlobalGeneric(context, global_object, vector); |
| 2008 return MarkAsCall(DefineFixed(result, r3), instr); | 1843 return MarkAsCall(DefineFixed(result, r2), instr); |
| 2009 } | 1844 } |
| 2010 | 1845 |
| 2011 | |
| 2012 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { | 1846 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
| 2013 LOperand* context = UseRegisterAtStart(instr->value()); | 1847 LOperand* context = UseRegisterAtStart(instr->value()); |
| 2014 LInstruction* result = | 1848 LInstruction* result = |
| 2015 DefineAsRegister(new (zone()) LLoadContextSlot(context)); | 1849 DefineAsRegister(new (zone()) LLoadContextSlot(context)); |
| 2016 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { | 1850 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
| 2017 result = AssignEnvironment(result); | 1851 result = AssignEnvironment(result); |
| 2018 } | 1852 } |
| 2019 return result; | 1853 return result; |
| 2020 } | 1854 } |
| 2021 | 1855 |
| 2022 | |
| 2023 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { | 1856 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { |
| 2024 LOperand* context; | 1857 LOperand* context; |
| 2025 LOperand* value; | 1858 LOperand* value; |
| 2026 if (instr->NeedsWriteBarrier()) { | 1859 if (instr->NeedsWriteBarrier()) { |
| 2027 context = UseTempRegister(instr->context()); | 1860 context = UseTempRegister(instr->context()); |
| 2028 value = UseTempRegister(instr->value()); | 1861 value = UseTempRegister(instr->value()); |
| 2029 } else { | 1862 } else { |
| 2030 context = UseRegister(instr->context()); | 1863 context = UseRegister(instr->context()); |
| 2031 value = UseRegister(instr->value()); | 1864 value = UseRegister(instr->value()); |
| 2032 } | 1865 } |
| 2033 LInstruction* result = new (zone()) LStoreContextSlot(context, value); | 1866 LInstruction* result = new (zone()) LStoreContextSlot(context, value); |
| 2034 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { | 1867 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
| 2035 result = AssignEnvironment(result); | 1868 result = AssignEnvironment(result); |
| 2036 } | 1869 } |
| 2037 return result; | 1870 return result; |
| 2038 } | 1871 } |
| 2039 | 1872 |
| 2040 | |
| 2041 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 1873 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
| 2042 LOperand* obj = UseRegisterAtStart(instr->object()); | 1874 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 2043 return DefineAsRegister(new (zone()) LLoadNamedField(obj)); | 1875 return DefineAsRegister(new (zone()) LLoadNamedField(obj)); |
| 2044 } | 1876 } |
| 2045 | 1877 |
| 2046 | |
| 2047 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { | 1878 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
| 2048 LOperand* context = UseFixed(instr->context(), cp); | 1879 LOperand* context = UseFixed(instr->context(), cp); |
| 2049 LOperand* object = | 1880 LOperand* object = |
| 2050 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister()); | 1881 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister()); |
| 2051 LOperand* vector = NULL; | 1882 LOperand* vector = NULL; |
| 2052 if (instr->HasVectorAndSlot()) { | 1883 if (instr->HasVectorAndSlot()) { |
| 2053 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); | 1884 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); |
| 2054 } | 1885 } |
| 2055 | 1886 |
| 2056 LInstruction* result = | 1887 LInstruction* result = |
| 2057 DefineFixed(new (zone()) LLoadNamedGeneric(context, object, vector), r3); | 1888 DefineFixed(new (zone()) LLoadNamedGeneric(context, object, vector), r2); |
| 2058 return MarkAsCall(result, instr); | 1889 return MarkAsCall(result, instr); |
| 2059 } | 1890 } |
| 2060 | 1891 |
| 2061 | |
| 2062 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( | 1892 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( |
| 2063 HLoadFunctionPrototype* instr) { | 1893 HLoadFunctionPrototype* instr) { |
| 2064 return AssignEnvironment(DefineAsRegister( | 1894 return AssignEnvironment(DefineAsRegister( |
| 2065 new (zone()) LLoadFunctionPrototype(UseRegister(instr->function())))); | 1895 new (zone()) LLoadFunctionPrototype(UseRegister(instr->function())))); |
| 2066 } | 1896 } |
| 2067 | 1897 |
| 2068 | |
| 2069 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { | 1898 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
| 2070 return DefineAsRegister(new (zone()) LLoadRoot); | 1899 return DefineAsRegister(new (zone()) LLoadRoot); |
| 2071 } | 1900 } |
| 2072 | 1901 |
| 2073 | |
| 2074 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 1902 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
| 2075 DCHECK(instr->key()->representation().IsSmiOrInteger32()); | 1903 DCHECK(instr->key()->representation().IsSmiOrInteger32()); |
| 2076 ElementsKind elements_kind = instr->elements_kind(); | 1904 ElementsKind elements_kind = instr->elements_kind(); |
| 2077 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 1905 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
| 2078 LInstruction* result = NULL; | 1906 LInstruction* result = NULL; |
| 2079 | 1907 |
| 2080 if (!instr->is_fixed_typed_array()) { | 1908 if (!instr->is_fixed_typed_array()) { |
| 2081 LOperand* obj = NULL; | 1909 LOperand* obj = NULL; |
| 2082 if (instr->representation().IsDouble()) { | 1910 if (instr->representation().IsDouble()) { |
| 2083 obj = UseRegister(instr->elements()); | 1911 obj = UseRegister(instr->elements()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2108 instr->RequiresHoleCheck() || | 1936 instr->RequiresHoleCheck() || |
| 2109 (instr->hole_mode() == CONVERT_HOLE_TO_UNDEFINED && info()->IsStub()); | 1937 (instr->hole_mode() == CONVERT_HOLE_TO_UNDEFINED && info()->IsStub()); |
| 2110 } | 1938 } |
| 2111 | 1939 |
| 2112 if (needs_environment) { | 1940 if (needs_environment) { |
| 2113 result = AssignEnvironment(result); | 1941 result = AssignEnvironment(result); |
| 2114 } | 1942 } |
| 2115 return result; | 1943 return result; |
| 2116 } | 1944 } |
| 2117 | 1945 |
| 2118 | |
| 2119 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1946 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 2120 LOperand* context = UseFixed(instr->context(), cp); | 1947 LOperand* context = UseFixed(instr->context(), cp); |
| 2121 LOperand* object = | 1948 LOperand* object = |
| 2122 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister()); | 1949 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister()); |
| 2123 LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister()); | 1950 LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister()); |
| 2124 LOperand* vector = NULL; | 1951 LOperand* vector = NULL; |
| 2125 if (instr->HasVectorAndSlot()) { | 1952 if (instr->HasVectorAndSlot()) { |
| 2126 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); | 1953 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); |
| 2127 } | 1954 } |
| 2128 | 1955 |
| 2129 LInstruction* result = DefineFixed( | 1956 LInstruction* result = DefineFixed( |
| 2130 new (zone()) LLoadKeyedGeneric(context, object, key, vector), r3); | 1957 new (zone()) LLoadKeyedGeneric(context, object, key, vector), r2); |
| 2131 return MarkAsCall(result, instr); | 1958 return MarkAsCall(result, instr); |
| 2132 } | 1959 } |
| 2133 | 1960 |
| 2134 | |
| 2135 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { | 1961 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
| 2136 if (!instr->is_fixed_typed_array()) { | 1962 if (!instr->is_fixed_typed_array()) { |
| 2137 DCHECK(instr->elements()->representation().IsTagged()); | 1963 DCHECK(instr->elements()->representation().IsTagged()); |
| 2138 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 1964 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 2139 LOperand* object = NULL; | 1965 LOperand* object = NULL; |
| 2140 LOperand* key = NULL; | 1966 LOperand* key = NULL; |
| 2141 LOperand* val = NULL; | 1967 LOperand* val = NULL; |
| 2142 | 1968 |
| 2143 if (instr->value()->representation().IsDouble()) { | 1969 if (instr->value()->representation().IsDouble()) { |
| 2144 object = UseRegisterAtStart(instr->elements()); | 1970 object = UseRegisterAtStart(instr->elements()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2164 (instr->value()->representation().IsDouble() && | 1990 (instr->value()->representation().IsDouble() && |
| 2165 IsDoubleOrFloatElementsKind(instr->elements_kind()))); | 1991 IsDoubleOrFloatElementsKind(instr->elements_kind()))); |
| 2166 DCHECK(instr->elements()->representation().IsExternal()); | 1992 DCHECK(instr->elements()->representation().IsExternal()); |
| 2167 LOperand* val = UseRegister(instr->value()); | 1993 LOperand* val = UseRegister(instr->value()); |
| 2168 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 1994 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
| 2169 LOperand* backing_store = UseRegister(instr->elements()); | 1995 LOperand* backing_store = UseRegister(instr->elements()); |
| 2170 LOperand* backing_store_owner = UseAny(instr->backing_store_owner()); | 1996 LOperand* backing_store_owner = UseAny(instr->backing_store_owner()); |
| 2171 return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner); | 1997 return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner); |
| 2172 } | 1998 } |
| 2173 | 1999 |
| 2174 | |
| 2175 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { | 2000 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
| 2176 LOperand* context = UseFixed(instr->context(), cp); | 2001 LOperand* context = UseFixed(instr->context(), cp); |
| 2177 LOperand* obj = | 2002 LOperand* obj = |
| 2178 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister()); | 2003 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister()); |
| 2179 LOperand* key = UseFixed(instr->key(), StoreDescriptor::NameRegister()); | 2004 LOperand* key = UseFixed(instr->key(), StoreDescriptor::NameRegister()); |
| 2180 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister()); | 2005 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister()); |
| 2181 | 2006 |
| 2182 DCHECK(instr->object()->representation().IsTagged()); | 2007 DCHECK(instr->object()->representation().IsTagged()); |
| 2183 DCHECK(instr->key()->representation().IsTagged()); | 2008 DCHECK(instr->key()->representation().IsTagged()); |
| 2184 DCHECK(instr->value()->representation().IsTagged()); | 2009 DCHECK(instr->value()->representation().IsTagged()); |
| 2185 | 2010 |
| 2186 LOperand* slot = NULL; | 2011 LOperand* slot = NULL; |
| 2187 LOperand* vector = NULL; | 2012 LOperand* vector = NULL; |
| 2188 if (instr->HasVectorAndSlot()) { | 2013 if (instr->HasVectorAndSlot()) { |
| 2189 slot = FixedTemp(VectorStoreICDescriptor::SlotRegister()); | 2014 slot = FixedTemp(VectorStoreICDescriptor::SlotRegister()); |
| 2190 vector = FixedTemp(VectorStoreICDescriptor::VectorRegister()); | 2015 vector = FixedTemp(VectorStoreICDescriptor::VectorRegister()); |
| 2191 } | 2016 } |
| 2192 | 2017 |
| 2193 LStoreKeyedGeneric* result = | 2018 LStoreKeyedGeneric* result = |
| 2194 new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector); | 2019 new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector); |
| 2195 return MarkAsCall(result, instr); | 2020 return MarkAsCall(result, instr); |
| 2196 } | 2021 } |
| 2197 | 2022 |
| 2198 | |
| 2199 LInstruction* LChunkBuilder::DoTransitionElementsKind( | 2023 LInstruction* LChunkBuilder::DoTransitionElementsKind( |
| 2200 HTransitionElementsKind* instr) { | 2024 HTransitionElementsKind* instr) { |
| 2201 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { | 2025 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { |
| 2202 LOperand* object = UseRegister(instr->object()); | 2026 LOperand* object = UseRegister(instr->object()); |
| 2203 LOperand* new_map_reg = TempRegister(); | 2027 LOperand* new_map_reg = TempRegister(); |
| 2204 LTransitionElementsKind* result = | 2028 LTransitionElementsKind* result = |
| 2205 new (zone()) LTransitionElementsKind(object, NULL, new_map_reg); | 2029 new (zone()) LTransitionElementsKind(object, NULL, new_map_reg); |
| 2206 return result; | 2030 return result; |
| 2207 } else { | 2031 } else { |
| 2208 LOperand* object = UseFixed(instr->object(), r3); | 2032 LOperand* object = UseFixed(instr->object(), r2); |
| 2209 LOperand* context = UseFixed(instr->context(), cp); | 2033 LOperand* context = UseFixed(instr->context(), cp); |
| 2210 LTransitionElementsKind* result = | 2034 LTransitionElementsKind* result = |
| 2211 new (zone()) LTransitionElementsKind(object, context, NULL); | 2035 new (zone()) LTransitionElementsKind(object, context, NULL); |
| 2212 return MarkAsCall(result, instr); | 2036 return MarkAsCall(result, instr); |
| 2213 } | 2037 } |
| 2214 } | 2038 } |
| 2215 | 2039 |
| 2216 | |
| 2217 LInstruction* LChunkBuilder::DoTrapAllocationMemento( | 2040 LInstruction* LChunkBuilder::DoTrapAllocationMemento( |
| 2218 HTrapAllocationMemento* instr) { | 2041 HTrapAllocationMemento* instr) { |
| 2219 LOperand* object = UseRegister(instr->object()); | 2042 LOperand* object = UseRegister(instr->object()); |
| 2220 LOperand* temp = TempRegister(); | 2043 LOperand* temp = TempRegister(); |
| 2221 LTrapAllocationMemento* result = | 2044 LTrapAllocationMemento* result = |
| 2222 new (zone()) LTrapAllocationMemento(object, temp); | 2045 new (zone()) LTrapAllocationMemento(object, temp); |
| 2223 return AssignEnvironment(result); | 2046 return AssignEnvironment(result); |
| 2224 } | 2047 } |
| 2225 | 2048 |
| 2226 | |
| 2227 LInstruction* LChunkBuilder::DoMaybeGrowElements(HMaybeGrowElements* instr) { | 2049 LInstruction* LChunkBuilder::DoMaybeGrowElements(HMaybeGrowElements* instr) { |
| 2228 info()->MarkAsDeferredCalling(); | 2050 info()->MarkAsDeferredCalling(); |
| 2229 LOperand* context = UseFixed(instr->context(), cp); | 2051 LOperand* context = UseFixed(instr->context(), cp); |
| 2230 LOperand* object = Use(instr->object()); | 2052 LOperand* object = Use(instr->object()); |
| 2231 LOperand* elements = Use(instr->elements()); | 2053 LOperand* elements = Use(instr->elements()); |
| 2232 LOperand* key = UseRegisterOrConstant(instr->key()); | 2054 LOperand* key = UseRegisterOrConstant(instr->key()); |
| 2233 LOperand* current_capacity = UseRegisterOrConstant(instr->current_capacity()); | 2055 LOperand* current_capacity = UseRegisterOrConstant(instr->current_capacity()); |
| 2234 | 2056 |
| 2235 LMaybeGrowElements* result = new (zone()) | 2057 LMaybeGrowElements* result = new (zone()) |
| 2236 LMaybeGrowElements(context, object, elements, key, current_capacity); | 2058 LMaybeGrowElements(context, object, elements, key, current_capacity); |
| 2237 DefineFixed(result, r3); | 2059 DefineFixed(result, r2); |
| 2238 return AssignPointerMap(AssignEnvironment(result)); | 2060 return AssignPointerMap(AssignEnvironment(result)); |
| 2239 } | 2061 } |
| 2240 | 2062 |
| 2241 | |
| 2242 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { | 2063 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { |
| 2243 bool is_in_object = instr->access().IsInobject(); | 2064 bool is_in_object = instr->access().IsInobject(); |
| 2244 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 2065 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 2245 bool needs_write_barrier_for_map = | 2066 bool needs_write_barrier_for_map = |
| 2246 instr->has_transition() && instr->NeedsWriteBarrierForMap(); | 2067 instr->has_transition() && instr->NeedsWriteBarrierForMap(); |
| 2247 | 2068 |
| 2248 LOperand* obj; | 2069 LOperand* obj; |
| 2249 if (needs_write_barrier) { | 2070 if (needs_write_barrier) { |
| 2250 obj = is_in_object ? UseRegister(instr->object()) | 2071 obj = is_in_object ? UseRegister(instr->object()) |
| 2251 : UseTempRegister(instr->object()); | 2072 : UseTempRegister(instr->object()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2262 } else { | 2083 } else { |
| 2263 val = UseRegister(instr->value()); | 2084 val = UseRegister(instr->value()); |
| 2264 } | 2085 } |
| 2265 | 2086 |
| 2266 // We need a temporary register for write barrier of the map field. | 2087 // We need a temporary register for write barrier of the map field. |
| 2267 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; | 2088 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; |
| 2268 | 2089 |
| 2269 return new (zone()) LStoreNamedField(obj, val, temp); | 2090 return new (zone()) LStoreNamedField(obj, val, temp); |
| 2270 } | 2091 } |
| 2271 | 2092 |
| 2272 | |
| 2273 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 2093 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
| 2274 LOperand* context = UseFixed(instr->context(), cp); | 2094 LOperand* context = UseFixed(instr->context(), cp); |
| 2275 LOperand* obj = | 2095 LOperand* obj = |
| 2276 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister()); | 2096 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister()); |
| 2277 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister()); | 2097 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister()); |
| 2278 LOperand* slot = NULL; | 2098 LOperand* slot = NULL; |
| 2279 LOperand* vector = NULL; | 2099 LOperand* vector = NULL; |
| 2280 if (instr->HasVectorAndSlot()) { | 2100 if (instr->HasVectorAndSlot()) { |
| 2281 slot = FixedTemp(VectorStoreICDescriptor::SlotRegister()); | 2101 slot = FixedTemp(VectorStoreICDescriptor::SlotRegister()); |
| 2282 vector = FixedTemp(VectorStoreICDescriptor::VectorRegister()); | 2102 vector = FixedTemp(VectorStoreICDescriptor::VectorRegister()); |
| 2283 } | 2103 } |
| 2284 | 2104 |
| 2285 LStoreNamedGeneric* result = | 2105 LStoreNamedGeneric* result = |
| 2286 new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector); | 2106 new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector); |
| 2287 return MarkAsCall(result, instr); | 2107 return MarkAsCall(result, instr); |
| 2288 } | 2108 } |
| 2289 | 2109 |
| 2290 | |
| 2291 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { | 2110 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { |
| 2292 LOperand* context = UseFixed(instr->context(), cp); | 2111 LOperand* context = UseFixed(instr->context(), cp); |
| 2293 LOperand* left = UseFixed(instr->left(), r4); | 2112 LOperand* left = UseFixed(instr->left(), r3); |
| 2294 LOperand* right = UseFixed(instr->right(), r3); | 2113 LOperand* right = UseFixed(instr->right(), r2); |
| 2295 return MarkAsCall( | 2114 return MarkAsCall( |
| 2296 DefineFixed(new (zone()) LStringAdd(context, left, right), r3), instr); | 2115 DefineFixed(new (zone()) LStringAdd(context, left, right), r2), instr); |
| 2297 } | 2116 } |
| 2298 | 2117 |
| 2299 | |
| 2300 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { | 2118 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
| 2301 LOperand* string = UseTempRegister(instr->string()); | 2119 LOperand* string = UseTempRegister(instr->string()); |
| 2302 LOperand* index = UseTempRegister(instr->index()); | 2120 LOperand* index = UseTempRegister(instr->index()); |
| 2303 LOperand* context = UseAny(instr->context()); | 2121 LOperand* context = UseAny(instr->context()); |
| 2304 LStringCharCodeAt* result = | 2122 LStringCharCodeAt* result = |
| 2305 new (zone()) LStringCharCodeAt(context, string, index); | 2123 new (zone()) LStringCharCodeAt(context, string, index); |
| 2306 return AssignPointerMap(DefineAsRegister(result)); | 2124 return AssignPointerMap(DefineAsRegister(result)); |
| 2307 } | 2125 } |
| 2308 | 2126 |
| 2309 | |
| 2310 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { | 2127 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { |
| 2311 LOperand* char_code = UseRegister(instr->value()); | 2128 LOperand* char_code = UseRegister(instr->value()); |
| 2312 LOperand* context = UseAny(instr->context()); | 2129 LOperand* context = UseAny(instr->context()); |
| 2313 LStringCharFromCode* result = | 2130 LStringCharFromCode* result = |
| 2314 new (zone()) LStringCharFromCode(context, char_code); | 2131 new (zone()) LStringCharFromCode(context, char_code); |
| 2315 return AssignPointerMap(DefineAsRegister(result)); | 2132 return AssignPointerMap(DefineAsRegister(result)); |
| 2316 } | 2133 } |
| 2317 | 2134 |
| 2318 | |
| 2319 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { | 2135 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { |
| 2320 info()->MarkAsDeferredCalling(); | 2136 info()->MarkAsDeferredCalling(); |
| 2321 LOperand* context = UseAny(instr->context()); | 2137 LOperand* context = UseAny(instr->context()); |
| 2322 LOperand* size = UseRegisterOrConstant(instr->size()); | 2138 LOperand* size = UseRegisterOrConstant(instr->size()); |
| 2323 LOperand* temp1 = TempRegister(); | 2139 LOperand* temp1 = TempRegister(); |
| 2324 LOperand* temp2 = TempRegister(); | 2140 LOperand* temp2 = TempRegister(); |
| 2325 LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2); | 2141 LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2); |
| 2326 return AssignPointerMap(DefineAsRegister(result)); | 2142 return AssignPointerMap(DefineAsRegister(result)); |
| 2327 } | 2143 } |
| 2328 | 2144 |
| 2329 | |
| 2330 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { | 2145 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { |
| 2331 DCHECK(argument_count_ == 0); | 2146 DCHECK(argument_count_ == 0); |
| 2332 allocator_->MarkAsOsrEntry(); | 2147 allocator_->MarkAsOsrEntry(); |
| 2333 current_block_->last_environment()->set_ast_id(instr->ast_id()); | 2148 current_block_->last_environment()->set_ast_id(instr->ast_id()); |
| 2334 return AssignEnvironment(new (zone()) LOsrEntry); | 2149 return AssignEnvironment(new (zone()) LOsrEntry); |
| 2335 } | 2150 } |
| 2336 | 2151 |
| 2337 | |
| 2338 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { | 2152 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { |
| 2339 LParameter* result = new (zone()) LParameter; | 2153 LParameter* result = new (zone()) LParameter; |
| 2340 if (instr->kind() == HParameter::STACK_PARAMETER) { | 2154 if (instr->kind() == HParameter::STACK_PARAMETER) { |
| 2341 int spill_index = chunk()->GetParameterStackSlot(instr->index()); | 2155 int spill_index = chunk()->GetParameterStackSlot(instr->index()); |
| 2342 return DefineAsSpilled(result, spill_index); | 2156 return DefineAsSpilled(result, spill_index); |
| 2343 } else { | 2157 } else { |
| 2344 DCHECK(info()->IsStub()); | 2158 DCHECK(info()->IsStub()); |
| 2345 CallInterfaceDescriptor descriptor = graph()->descriptor(); | 2159 CallInterfaceDescriptor descriptor = graph()->descriptor(); |
| 2346 int index = static_cast<int>(instr->index()); | 2160 int index = static_cast<int>(instr->index()); |
| 2347 Register reg = descriptor.GetRegisterParameter(index); | 2161 Register reg = descriptor.GetRegisterParameter(index); |
| 2348 return DefineFixed(result, reg); | 2162 return DefineFixed(result, reg); |
| 2349 } | 2163 } |
| 2350 } | 2164 } |
| 2351 | 2165 |
| 2352 | |
| 2353 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { | 2166 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { |
| 2354 // Use an index that corresponds to the location in the unoptimized frame, | 2167 // Use an index that corresponds to the location in the unoptimized frame, |
| 2355 // which the optimized frame will subsume. | 2168 // which the optimized frame will subsume. |
| 2356 int env_index = instr->index(); | 2169 int env_index = instr->index(); |
| 2357 int spill_index = 0; | 2170 int spill_index = 0; |
| 2358 if (instr->environment()->is_parameter_index(env_index)) { | 2171 if (instr->environment()->is_parameter_index(env_index)) { |
| 2359 spill_index = chunk()->GetParameterStackSlot(env_index); | 2172 spill_index = chunk()->GetParameterStackSlot(env_index); |
| 2360 } else { | 2173 } else { |
| 2361 spill_index = env_index - instr->environment()->first_local_index(); | 2174 spill_index = env_index - instr->environment()->first_local_index(); |
| 2362 if (spill_index > LUnallocated::kMaxFixedSlotIndex) { | 2175 if (spill_index > LUnallocated::kMaxFixedSlotIndex) { |
| 2363 Retry(kTooManySpillSlotsNeededForOSR); | 2176 Retry(kTooManySpillSlotsNeededForOSR); |
| 2364 spill_index = 0; | 2177 spill_index = 0; |
| 2365 } | 2178 } |
| 2366 spill_index += StandardFrameConstants::kFixedSlotCount; | 2179 spill_index += StandardFrameConstants::kFixedSlotCount; |
| 2367 } | 2180 } |
| 2368 return DefineAsSpilled(new (zone()) LUnknownOSRValue, spill_index); | 2181 return DefineAsSpilled(new (zone()) LUnknownOSRValue, spill_index); |
| 2369 } | 2182 } |
| 2370 | 2183 |
| 2371 | |
| 2372 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { | 2184 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { |
| 2373 // There are no real uses of the arguments object. | 2185 // There are no real uses of the arguments object. |
| 2374 // arguments.length and element access are supported directly on | 2186 // arguments.length and element access are supported directly on |
| 2375 // stack arguments, and any real arguments object use causes a bailout. | 2187 // stack arguments, and any real arguments object use causes a bailout. |
| 2376 // So this value is never used. | 2188 // So this value is never used. |
| 2377 return NULL; | 2189 return NULL; |
| 2378 } | 2190 } |
| 2379 | 2191 |
| 2380 | |
| 2381 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) { | 2192 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) { |
| 2382 instr->ReplayEnvironment(current_block_->last_environment()); | 2193 instr->ReplayEnvironment(current_block_->last_environment()); |
| 2383 | 2194 |
| 2384 // There are no real uses of a captured object. | 2195 // There are no real uses of a captured object. |
| 2385 return NULL; | 2196 return NULL; |
| 2386 } | 2197 } |
| 2387 | 2198 |
| 2388 | |
| 2389 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { | 2199 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { |
| 2390 info()->MarkAsRequiresFrame(); | 2200 info()->MarkAsRequiresFrame(); |
| 2391 LOperand* args = UseRegister(instr->arguments()); | 2201 LOperand* args = UseRegister(instr->arguments()); |
| 2392 LOperand* length = UseRegisterOrConstantAtStart(instr->length()); | 2202 LOperand* length = UseRegisterOrConstantAtStart(instr->length()); |
| 2393 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); | 2203 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); |
| 2394 return DefineAsRegister(new (zone()) LAccessArgumentsAt(args, length, index)); | 2204 return DefineAsRegister(new (zone()) LAccessArgumentsAt(args, length, index)); |
| 2395 } | 2205 } |
| 2396 | 2206 |
| 2397 | |
| 2398 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) { | 2207 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) { |
| 2399 LOperand* object = UseFixed(instr->value(), r3); | 2208 LOperand* object = UseFixed(instr->value(), r2); |
| 2400 LToFastProperties* result = new (zone()) LToFastProperties(object); | 2209 LToFastProperties* result = new (zone()) LToFastProperties(object); |
| 2401 return MarkAsCall(DefineFixed(result, r3), instr); | 2210 return MarkAsCall(DefineFixed(result, r2), instr); |
| 2402 } | 2211 } |
| 2403 | 2212 |
| 2404 | |
| 2405 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 2213 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
| 2406 LOperand* context = UseFixed(instr->context(), cp); | 2214 LOperand* context = UseFixed(instr->context(), cp); |
| 2407 LOperand* value = UseFixed(instr->value(), r6); | 2215 LOperand* value = UseFixed(instr->value(), r5); |
| 2408 LTypeof* result = new (zone()) LTypeof(context, value); | 2216 LTypeof* result = new (zone()) LTypeof(context, value); |
| 2409 return MarkAsCall(DefineFixed(result, r3), instr); | 2217 return MarkAsCall(DefineFixed(result, r2), instr); |
| 2410 } | 2218 } |
| 2411 | 2219 |
| 2412 | |
| 2413 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { | 2220 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { |
| 2414 return new (zone()) LTypeofIsAndBranch(UseRegister(instr->value())); | 2221 return new (zone()) LTypeofIsAndBranch(UseRegister(instr->value())); |
| 2415 } | 2222 } |
| 2416 | 2223 |
| 2417 | |
| 2418 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 2224 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 2419 instr->ReplayEnvironment(current_block_->last_environment()); | 2225 instr->ReplayEnvironment(current_block_->last_environment()); |
| 2420 return NULL; | 2226 return NULL; |
| 2421 } | 2227 } |
| 2422 | 2228 |
| 2423 | |
| 2424 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { | 2229 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { |
| 2425 if (instr->is_function_entry()) { | 2230 if (instr->is_function_entry()) { |
| 2426 LOperand* context = UseFixed(instr->context(), cp); | 2231 LOperand* context = UseFixed(instr->context(), cp); |
| 2427 return MarkAsCall(new (zone()) LStackCheck(context), instr); | 2232 return MarkAsCall(new (zone()) LStackCheck(context), instr); |
| 2428 } else { | 2233 } else { |
| 2429 DCHECK(instr->is_backwards_branch()); | 2234 DCHECK(instr->is_backwards_branch()); |
| 2430 LOperand* context = UseAny(instr->context()); | 2235 LOperand* context = UseAny(instr->context()); |
| 2431 return AssignEnvironment( | 2236 return AssignEnvironment( |
| 2432 AssignPointerMap(new (zone()) LStackCheck(context))); | 2237 AssignPointerMap(new (zone()) LStackCheck(context))); |
| 2433 } | 2238 } |
| 2434 } | 2239 } |
| 2435 | 2240 |
| 2436 | |
| 2437 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { | 2241 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { |
| 2438 HEnvironment* outer = current_block_->last_environment(); | 2242 HEnvironment* outer = current_block_->last_environment(); |
| 2439 outer->set_ast_id(instr->ReturnId()); | 2243 outer->set_ast_id(instr->ReturnId()); |
| 2440 HConstant* undefined = graph()->GetConstantUndefined(); | 2244 HConstant* undefined = graph()->GetConstantUndefined(); |
| 2441 HEnvironment* inner = outer->CopyForInlining( | 2245 HEnvironment* inner = outer->CopyForInlining( |
| 2442 instr->closure(), instr->arguments_count(), instr->function(), undefined, | 2246 instr->closure(), instr->arguments_count(), instr->function(), undefined, |
| 2443 instr->inlining_kind()); | 2247 instr->inlining_kind()); |
| 2444 // Only replay binding of arguments object if it wasn't removed from graph. | 2248 // Only replay binding of arguments object if it wasn't removed from graph. |
| 2445 if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) { | 2249 if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) { |
| 2446 inner->Bind(instr->arguments_var(), instr->arguments_object()); | 2250 inner->Bind(instr->arguments_var(), instr->arguments_object()); |
| 2447 } | 2251 } |
| 2448 inner->BindContext(instr->closure_context()); | 2252 inner->BindContext(instr->closure_context()); |
| 2449 inner->set_entry(instr); | 2253 inner->set_entry(instr); |
| 2450 current_block_->UpdateEnvironment(inner); | 2254 current_block_->UpdateEnvironment(inner); |
| 2451 chunk_->AddInlinedFunction(instr->shared()); | 2255 chunk_->AddInlinedFunction(instr->shared()); |
| 2452 return NULL; | 2256 return NULL; |
| 2453 } | 2257 } |
| 2454 | 2258 |
| 2455 | |
| 2456 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2259 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 2457 LInstruction* pop = NULL; | 2260 LInstruction* pop = NULL; |
| 2458 | 2261 |
| 2459 HEnvironment* env = current_block_->last_environment(); | 2262 HEnvironment* env = current_block_->last_environment(); |
| 2460 | 2263 |
| 2461 if (env->entry()->arguments_pushed()) { | 2264 if (env->entry()->arguments_pushed()) { |
| 2462 int argument_count = env->arguments_environment()->parameter_count(); | 2265 int argument_count = env->arguments_environment()->parameter_count(); |
| 2463 pop = new (zone()) LDrop(argument_count); | 2266 pop = new (zone()) LDrop(argument_count); |
| 2464 DCHECK(instr->argument_delta() == -argument_count); | 2267 DCHECK(instr->argument_delta() == -argument_count); |
| 2465 } | 2268 } |
| 2466 | 2269 |
| 2467 HEnvironment* outer = | 2270 HEnvironment* outer = |
| 2468 current_block_->last_environment()->DiscardInlined(false); | 2271 current_block_->last_environment()->DiscardInlined(false); |
| 2469 current_block_->UpdateEnvironment(outer); | 2272 current_block_->UpdateEnvironment(outer); |
| 2470 | 2273 |
| 2471 return pop; | 2274 return pop; |
| 2472 } | 2275 } |
| 2473 | 2276 |
| 2474 | |
| 2475 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { | 2277 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { |
| 2476 LOperand* context = UseFixed(instr->context(), cp); | 2278 LOperand* context = UseFixed(instr->context(), cp); |
| 2477 LOperand* object = UseFixed(instr->enumerable(), r3); | 2279 LOperand* object = UseFixed(instr->enumerable(), r2); |
| 2478 LForInPrepareMap* result = new (zone()) LForInPrepareMap(context, object); | 2280 LForInPrepareMap* result = new (zone()) LForInPrepareMap(context, object); |
| 2479 return MarkAsCall(DefineFixed(result, r3), instr, CAN_DEOPTIMIZE_EAGERLY); | 2281 return MarkAsCall(DefineFixed(result, r2), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 2480 } | 2282 } |
| 2481 | 2283 |
| 2482 | |
| 2483 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) { | 2284 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) { |
| 2484 LOperand* map = UseRegister(instr->map()); | 2285 LOperand* map = UseRegister(instr->map()); |
| 2485 return AssignEnvironment( | 2286 return AssignEnvironment( |
| 2486 DefineAsRegister(new (zone()) LForInCacheArray(map))); | 2287 DefineAsRegister(new (zone()) LForInCacheArray(map))); |
| 2487 } | 2288 } |
| 2488 | 2289 |
| 2489 | |
| 2490 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) { | 2290 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) { |
| 2491 LOperand* value = UseRegisterAtStart(instr->value()); | 2291 LOperand* value = UseRegisterAtStart(instr->value()); |
| 2492 LOperand* map = UseRegisterAtStart(instr->map()); | 2292 LOperand* map = UseRegisterAtStart(instr->map()); |
| 2493 return AssignEnvironment(new (zone()) LCheckMapValue(value, map)); | 2293 return AssignEnvironment(new (zone()) LCheckMapValue(value, map)); |
| 2494 } | 2294 } |
| 2495 | 2295 |
| 2496 | |
| 2497 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2296 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2498 LOperand* object = UseRegister(instr->object()); | 2297 LOperand* object = UseRegister(instr->object()); |
| 2499 LOperand* index = UseTempRegister(instr->index()); | 2298 LOperand* index = UseTempRegister(instr->index()); |
| 2500 LLoadFieldByIndex* load = new (zone()) LLoadFieldByIndex(object, index); | 2299 LLoadFieldByIndex* load = new (zone()) LLoadFieldByIndex(object, index); |
| 2501 LInstruction* result = DefineSameAsFirst(load); | 2300 LInstruction* result = DefineSameAsFirst(load); |
| 2502 return AssignPointerMap(result); | 2301 return AssignPointerMap(result); |
| 2503 } | 2302 } |
| 2504 | 2303 |
| 2505 | |
| 2506 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) { | 2304 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) { |
| 2507 LOperand* context = UseRegisterAtStart(instr->context()); | 2305 LOperand* context = UseRegisterAtStart(instr->context()); |
| 2508 return new (zone()) LStoreFrameContext(context); | 2306 return new (zone()) LStoreFrameContext(context); |
| 2509 } | 2307 } |
| 2510 | 2308 |
| 2511 } // namespace internal | 2309 } // namespace internal |
| 2512 } // namespace v8 | 2310 } // namespace v8 |
| OLD | NEW |