| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" |
| 29 |
| 30 #if defined(V8_TARGET_ARCH_IA32) |
| 31 |
| 28 #include "ia32/lithium-ia32.h" | 32 #include "ia32/lithium-ia32.h" |
| 29 #include "ia32/lithium-codegen-ia32.h" | 33 #include "ia32/lithium-codegen-ia32.h" |
| 30 | 34 |
| 31 namespace v8 { | 35 namespace v8 { |
| 32 namespace internal { | 36 namespace internal { |
| 33 | 37 |
| 34 #define DEFINE_COMPILE(type) \ | 38 #define DEFINE_COMPILE(type) \ |
| 35 void L##type::CompileToNative(LCodeGen* generator) { \ | 39 void L##type::CompileToNative(LCodeGen* generator) { \ |
| 36 generator->Do##type(this); \ | 40 generator->Do##type(this); \ |
| 37 } | 41 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 57 | 61 |
| 58 | 62 |
| 59 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, | 63 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, |
| 60 LOperand* spill_operand) { | 64 LOperand* spill_operand) { |
| 61 ASSERT(spill_operand->IsDoubleStackSlot()); | 65 ASSERT(spill_operand->IsDoubleStackSlot()); |
| 62 ASSERT(double_register_spills_[allocation_index] == NULL); | 66 ASSERT(double_register_spills_[allocation_index] == NULL); |
| 63 double_register_spills_[allocation_index] = spill_operand; | 67 double_register_spills_[allocation_index] = spill_operand; |
| 64 } | 68 } |
| 65 | 69 |
| 66 | 70 |
| 67 void LInstruction::PrintTo(StringStream* stream) const { | 71 void LInstruction::PrintTo(StringStream* stream) { |
| 68 stream->Add("%s ", this->Mnemonic()); | 72 stream->Add("%s ", this->Mnemonic()); |
| 69 if (HasResult()) { | 73 if (HasResult()) { |
| 70 result()->PrintTo(stream); | 74 PrintOutputOperandTo(stream); |
| 71 stream->Add(" "); | |
| 72 } | 75 } |
| 76 |
| 73 PrintDataTo(stream); | 77 PrintDataTo(stream); |
| 74 | 78 |
| 75 if (HasEnvironment()) { | 79 if (HasEnvironment()) { |
| 76 stream->Add(" "); | 80 stream->Add(" "); |
| 77 environment()->PrintTo(stream); | 81 environment()->PrintTo(stream); |
| 78 } | 82 } |
| 79 | 83 |
| 80 if (HasPointerMap()) { | 84 if (HasPointerMap()) { |
| 81 stream->Add(" "); | 85 stream->Add(" "); |
| 82 pointer_map()->PrintTo(stream); | 86 pointer_map()->PrintTo(stream); |
| 83 } | 87 } |
| 84 } | 88 } |
| 85 | 89 |
| 86 | 90 |
| 87 void LLabel::PrintDataTo(StringStream* stream) const { | 91 template<int R, int I, int T> |
| 92 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) { |
| 93 for (int i = 0; i < I; i++) { |
| 94 stream->Add(i == 0 ? "= " : " "); |
| 95 inputs_.at(i)->PrintTo(stream); |
| 96 } |
| 97 } |
| 98 |
| 99 |
| 100 template<int R, int I, int T> |
| 101 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) { |
| 102 if (this->HasResult()) { |
| 103 this->result()->PrintTo(stream); |
| 104 stream->Add(" "); |
| 105 } |
| 106 } |
| 107 |
| 108 |
| 109 void LLabel::PrintDataTo(StringStream* stream) { |
| 88 LGap::PrintDataTo(stream); | 110 LGap::PrintDataTo(stream); |
| 89 LLabel* rep = replacement(); | 111 LLabel* rep = replacement(); |
| 90 if (rep != NULL) { | 112 if (rep != NULL) { |
| 91 stream->Add(" Dead block replaced with B%d", rep->block_id()); | 113 stream->Add(" Dead block replaced with B%d", rep->block_id()); |
| 92 } | 114 } |
| 93 } | 115 } |
| 94 | 116 |
| 95 | |
| 96 bool LParallelMove::IsRedundant() const { | |
| 97 for (int i = 0; i < move_operands_.length(); ++i) { | |
| 98 if (!move_operands_[i].IsRedundant()) return false; | |
| 99 } | |
| 100 return true; | |
| 101 } | |
| 102 | |
| 103 | |
| 104 void LParallelMove::PrintDataTo(StringStream* stream) const { | |
| 105 for (int i = move_operands_.length() - 1; i >= 0; --i) { | |
| 106 if (!move_operands_[i].IsEliminated()) { | |
| 107 LOperand* from = move_operands_[i].from(); | |
| 108 LOperand* to = move_operands_[i].to(); | |
| 109 if (from->Equals(to)) { | |
| 110 to->PrintTo(stream); | |
| 111 } else { | |
| 112 to->PrintTo(stream); | |
| 113 stream->Add(" = "); | |
| 114 from->PrintTo(stream); | |
| 115 } | |
| 116 stream->Add("; "); | |
| 117 } | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 | 117 |
| 122 bool LGap::IsRedundant() const { | 118 bool LGap::IsRedundant() const { |
| 123 for (int i = 0; i < 4; i++) { | 119 for (int i = 0; i < 4; i++) { |
| 124 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { | 120 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { |
| 125 return false; | 121 return false; |
| 126 } | 122 } |
| 127 } | 123 } |
| 128 | 124 |
| 129 return true; | 125 return true; |
| 130 } | 126 } |
| 131 | 127 |
| 132 | 128 |
| 133 void LGap::PrintDataTo(StringStream* stream) const { | 129 void LGap::PrintDataTo(StringStream* stream) { |
| 134 for (int i = 0; i < 4; i++) { | 130 for (int i = 0; i < 4; i++) { |
| 135 stream->Add("("); | 131 stream->Add("("); |
| 136 if (parallel_moves_[i] != NULL) { | 132 if (parallel_moves_[i] != NULL) { |
| 137 parallel_moves_[i]->PrintDataTo(stream); | 133 parallel_moves_[i]->PrintDataTo(stream); |
| 138 } | 134 } |
| 139 stream->Add(") "); | 135 stream->Add(") "); |
| 140 } | 136 } |
| 141 } | 137 } |
| 142 | 138 |
| 143 | 139 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 162 case Token::MUL: return "mul-t"; | 158 case Token::MUL: return "mul-t"; |
| 163 case Token::MOD: return "mod-t"; | 159 case Token::MOD: return "mod-t"; |
| 164 case Token::DIV: return "div-t"; | 160 case Token::DIV: return "div-t"; |
| 165 default: | 161 default: |
| 166 UNREACHABLE(); | 162 UNREACHABLE(); |
| 167 return NULL; | 163 return NULL; |
| 168 } | 164 } |
| 169 } | 165 } |
| 170 | 166 |
| 171 | 167 |
| 172 | 168 void LGoto::PrintDataTo(StringStream* stream) { |
| 173 void LBinaryOperation::PrintDataTo(StringStream* stream) const { | |
| 174 stream->Add("= "); | |
| 175 left()->PrintTo(stream); | |
| 176 stream->Add(" "); | |
| 177 right()->PrintTo(stream); | |
| 178 } | |
| 179 | |
| 180 | |
| 181 void LGoto::PrintDataTo(StringStream* stream) const { | |
| 182 stream->Add("B%d", block_id()); | 169 stream->Add("B%d", block_id()); |
| 183 } | 170 } |
| 184 | 171 |
| 185 | 172 |
| 186 void LBranch::PrintDataTo(StringStream* stream) const { | 173 void LBranch::PrintDataTo(StringStream* stream) { |
| 187 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); | 174 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); |
| 188 input()->PrintTo(stream); | 175 input()->PrintTo(stream); |
| 189 } | 176 } |
| 190 | 177 |
| 191 | 178 |
| 192 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) const { | 179 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) { |
| 193 stream->Add("if "); | 180 stream->Add("if "); |
| 194 left()->PrintTo(stream); | 181 left()->PrintTo(stream); |
| 195 stream->Add(" %s ", Token::String(op())); | 182 stream->Add(" %s ", Token::String(op())); |
| 196 right()->PrintTo(stream); | 183 right()->PrintTo(stream); |
| 197 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()); |
| 198 } | 185 } |
| 199 | 186 |
| 200 | 187 |
| 201 void LIsNullAndBranch::PrintDataTo(StringStream* stream) const { | 188 void LIsNullAndBranch::PrintDataTo(StringStream* stream) { |
| 202 stream->Add("if "); | 189 stream->Add("if "); |
| 203 input()->PrintTo(stream); | 190 input()->PrintTo(stream); |
| 204 stream->Add(is_strict() ? " === null" : " == null"); | 191 stream->Add(is_strict() ? " === null" : " == null"); |
| 205 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); | 192 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); |
| 206 } | 193 } |
| 207 | 194 |
| 208 | 195 |
| 209 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) const { | 196 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) { |
| 210 stream->Add("if is_object("); | 197 stream->Add("if is_object("); |
| 211 input()->PrintTo(stream); | 198 input()->PrintTo(stream); |
| 212 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 199 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 213 } | 200 } |
| 214 | 201 |
| 215 | 202 |
| 216 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) const { | 203 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { |
| 217 stream->Add("if is_smi("); | 204 stream->Add("if is_smi("); |
| 218 input()->PrintTo(stream); | 205 input()->PrintTo(stream); |
| 219 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 206 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 220 } | 207 } |
| 221 | 208 |
| 222 | 209 |
| 223 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) const { | 210 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { |
| 224 stream->Add("if has_instance_type("); | 211 stream->Add("if has_instance_type("); |
| 225 input()->PrintTo(stream); | 212 input()->PrintTo(stream); |
| 226 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 213 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 227 } | 214 } |
| 228 | 215 |
| 229 | 216 |
| 230 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) const { | 217 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) { |
| 231 stream->Add("if has_cached_array_index("); | 218 stream->Add("if has_cached_array_index("); |
| 232 input()->PrintTo(stream); | 219 input()->PrintTo(stream); |
| 233 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 220 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 234 } | 221 } |
| 235 | 222 |
| 236 | 223 |
| 237 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) const { | 224 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { |
| 238 stream->Add("if class_of_test("); | 225 stream->Add("if class_of_test("); |
| 239 input()->PrintTo(stream); | 226 input()->PrintTo(stream); |
| 240 stream->Add(", \"%o\") then B%d else B%d", | 227 stream->Add(", \"%o\") then B%d else B%d", |
| 241 *hydrogen()->class_name(), | 228 *hydrogen()->class_name(), |
| 242 true_block_id(), | 229 true_block_id(), |
| 243 false_block_id()); | 230 false_block_id()); |
| 244 } | 231 } |
| 245 | 232 |
| 246 | 233 |
| 247 void LTypeofIs::PrintDataTo(StringStream* stream) const { | 234 void LTypeofIs::PrintDataTo(StringStream* stream) { |
| 248 input()->PrintTo(stream); | 235 input()->PrintTo(stream); |
| 249 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString()); | 236 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString()); |
| 250 } | 237 } |
| 251 | 238 |
| 252 | 239 |
| 253 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) const { | 240 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { |
| 254 stream->Add("if typeof "); | 241 stream->Add("if typeof "); |
| 255 input()->PrintTo(stream); | 242 input()->PrintTo(stream); |
| 256 stream->Add(" == \"%s\" then B%d else B%d", | 243 stream->Add(" == \"%s\" then B%d else B%d", |
| 257 *hydrogen()->type_literal()->ToCString(), | 244 *hydrogen()->type_literal()->ToCString(), |
| 258 true_block_id(), false_block_id()); | 245 true_block_id(), false_block_id()); |
| 259 } | 246 } |
| 260 | 247 |
| 261 | 248 |
| 262 void LCallConstantFunction::PrintDataTo(StringStream* stream) const { | 249 void LCallConstantFunction::PrintDataTo(StringStream* stream) { |
| 263 stream->Add("#%d / ", arity()); | 250 stream->Add("#%d / ", arity()); |
| 264 } | 251 } |
| 265 | 252 |
| 266 | 253 |
| 267 void LUnaryMathOperation::PrintDataTo(StringStream* stream) const { | 254 void LUnaryMathOperation::PrintDataTo(StringStream* stream) { |
| 268 stream->Add("/%s ", hydrogen()->OpName()); | 255 stream->Add("/%s ", hydrogen()->OpName()); |
| 269 input()->PrintTo(stream); | 256 input()->PrintTo(stream); |
| 270 } | 257 } |
| 271 | 258 |
| 272 | 259 |
| 273 void LCallKeyed::PrintDataTo(StringStream* stream) const { | 260 void LCallKeyed::PrintDataTo(StringStream* stream) { |
| 274 stream->Add("[ecx] #%d / ", arity()); | 261 stream->Add("[ecx] #%d / ", arity()); |
| 275 } | 262 } |
| 276 | 263 |
| 277 | 264 |
| 278 void LCallNamed::PrintDataTo(StringStream* stream) const { | 265 void LCallNamed::PrintDataTo(StringStream* stream) { |
| 279 SmartPointer<char> name_string = name()->ToCString(); | 266 SmartPointer<char> name_string = name()->ToCString(); |
| 280 stream->Add("%s #%d / ", *name_string, arity()); | 267 stream->Add("%s #%d / ", *name_string, arity()); |
| 281 } | 268 } |
| 282 | 269 |
| 283 | 270 |
| 284 void LCallGlobal::PrintDataTo(StringStream* stream) const { | 271 void LCallGlobal::PrintDataTo(StringStream* stream) { |
| 285 SmartPointer<char> name_string = name()->ToCString(); | 272 SmartPointer<char> name_string = name()->ToCString(); |
| 286 stream->Add("%s #%d / ", *name_string, arity()); | 273 stream->Add("%s #%d / ", *name_string, arity()); |
| 287 } | 274 } |
| 288 | 275 |
| 289 | 276 |
| 290 void LCallKnownGlobal::PrintDataTo(StringStream* stream) const { | 277 void LCallKnownGlobal::PrintDataTo(StringStream* stream) { |
| 291 stream->Add("#%d / ", arity()); | 278 stream->Add("#%d / ", arity()); |
| 292 } | 279 } |
| 293 | 280 |
| 294 | 281 |
| 295 void LCallNew::PrintDataTo(StringStream* stream) const { | 282 void LCallNew::PrintDataTo(StringStream* stream) { |
| 296 LUnaryOperation::PrintDataTo(stream); | 283 stream->Add("= "); |
| 284 input()->PrintTo(stream); |
| 297 stream->Add(" #%d / ", arity()); | 285 stream->Add(" #%d / ", arity()); |
| 298 } | 286 } |
| 299 | 287 |
| 300 | 288 |
| 301 void LClassOfTest::PrintDataTo(StringStream* stream) const { | 289 void LClassOfTest::PrintDataTo(StringStream* stream) { |
| 302 stream->Add("= class_of_test("); | 290 stream->Add("= class_of_test("); |
| 303 input()->PrintTo(stream); | 291 input()->PrintTo(stream); |
| 304 stream->Add(", \"%o\")", *hydrogen()->class_name()); | 292 stream->Add(", \"%o\")", *hydrogen()->class_name()); |
| 305 } | 293 } |
| 306 | 294 |
| 307 | 295 |
| 308 void LUnaryOperation::PrintDataTo(StringStream* stream) const { | 296 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { |
| 309 stream->Add("= "); | |
| 310 input()->PrintTo(stream); | |
| 311 } | |
| 312 | |
| 313 | |
| 314 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) const { | |
| 315 arguments()->PrintTo(stream); | 297 arguments()->PrintTo(stream); |
| 316 | 298 |
| 317 stream->Add(" length "); | 299 stream->Add(" length "); |
| 318 length()->PrintTo(stream); | 300 length()->PrintTo(stream); |
| 319 | 301 |
| 320 stream->Add(" index "); | 302 stream->Add(" index "); |
| 321 index()->PrintTo(stream); | 303 index()->PrintTo(stream); |
| 322 } | 304 } |
| 323 | 305 |
| 324 | 306 |
| 325 LChunk::LChunk(HGraph* graph) | |
| 326 : spill_slot_count_(0), | |
| 327 graph_(graph), | |
| 328 instructions_(32), | |
| 329 pointer_maps_(8), | |
| 330 inlined_closures_(1) { | |
| 331 } | |
| 332 | |
| 333 | |
| 334 void LChunk::Verify() const { | |
| 335 // TODO(twuerthinger): Implement verification for chunk. | |
| 336 } | |
| 337 | |
| 338 | |
| 339 int LChunk::GetNextSpillIndex(bool is_double) { | 307 int LChunk::GetNextSpillIndex(bool is_double) { |
| 340 // Skip a slot if for a double-width slot. | 308 // Skip a slot if for a double-width slot. |
| 341 if (is_double) spill_slot_count_++; | 309 if (is_double) spill_slot_count_++; |
| 342 return spill_slot_count_++; | 310 return spill_slot_count_++; |
| 343 } | 311 } |
| 344 | 312 |
| 345 | 313 |
| 346 LOperand* LChunk::GetNextSpillSlot(bool is_double) { | 314 LOperand* LChunk::GetNextSpillSlot(bool is_double) { |
| 347 int index = GetNextSpillIndex(is_double); | 315 int index = GetNextSpillIndex(is_double); |
| 348 if (is_double) { | 316 if (is_double) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 | 351 |
| 384 if (can_eliminate) { | 352 if (can_eliminate) { |
| 385 label->set_replacement(GetLabel(goto_instr->block_id())); | 353 label->set_replacement(GetLabel(goto_instr->block_id())); |
| 386 } | 354 } |
| 387 } | 355 } |
| 388 } | 356 } |
| 389 } | 357 } |
| 390 } | 358 } |
| 391 | 359 |
| 392 | 360 |
| 393 void LStoreNamed::PrintDataTo(StringStream* stream) const { | 361 void LStoreNamed::PrintDataTo(StringStream* stream) { |
| 394 object()->PrintTo(stream); | 362 object()->PrintTo(stream); |
| 395 stream->Add("."); | 363 stream->Add("."); |
| 396 stream->Add(*String::cast(*name())->ToCString()); | 364 stream->Add(*String::cast(*name())->ToCString()); |
| 397 stream->Add(" <- "); | 365 stream->Add(" <- "); |
| 398 value()->PrintTo(stream); | 366 value()->PrintTo(stream); |
| 399 } | 367 } |
| 400 | 368 |
| 401 | 369 |
| 402 void LStoreKeyed::PrintDataTo(StringStream* stream) const { | 370 void LStoreKeyed::PrintDataTo(StringStream* stream) { |
| 403 object()->PrintTo(stream); | 371 object()->PrintTo(stream); |
| 404 stream->Add("["); | 372 stream->Add("["); |
| 405 key()->PrintTo(stream); | 373 key()->PrintTo(stream); |
| 406 stream->Add("] <- "); | 374 stream->Add("] <- "); |
| 407 value()->PrintTo(stream); | 375 value()->PrintTo(stream); |
| 408 } | 376 } |
| 409 | 377 |
| 410 | 378 |
| 411 int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { | 379 int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { |
| 412 LGap* gap = new LGap(block); | 380 LGap* gap = new LGap(block); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 while (!IsGapAt(index)) index--; | 433 while (!IsGapAt(index)) index--; |
| 466 return index; | 434 return index; |
| 467 } | 435 } |
| 468 | 436 |
| 469 | 437 |
| 470 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { | 438 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { |
| 471 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); | 439 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); |
| 472 } | 440 } |
| 473 | 441 |
| 474 | 442 |
| 475 class LGapNode: public ZoneObject { | |
| 476 public: | |
| 477 explicit LGapNode(LOperand* operand) | |
| 478 : operand_(operand), resolved_(false), visited_id_(-1) { } | |
| 479 | |
| 480 LOperand* operand() const { return operand_; } | |
| 481 bool IsResolved() const { return !IsAssigned() || resolved_; } | |
| 482 void MarkResolved() { | |
| 483 ASSERT(!IsResolved()); | |
| 484 resolved_ = true; | |
| 485 } | |
| 486 int visited_id() const { return visited_id_; } | |
| 487 void set_visited_id(int id) { | |
| 488 ASSERT(id > visited_id_); | |
| 489 visited_id_ = id; | |
| 490 } | |
| 491 | |
| 492 bool IsAssigned() const { return assigned_from_.is_set(); } | |
| 493 LGapNode* assigned_from() const { return assigned_from_.get(); } | |
| 494 void set_assigned_from(LGapNode* n) { assigned_from_.set(n); } | |
| 495 | |
| 496 private: | |
| 497 LOperand* operand_; | |
| 498 SetOncePointer<LGapNode> assigned_from_; | |
| 499 bool resolved_; | |
| 500 int visited_id_; | |
| 501 }; | |
| 502 | |
| 503 | |
| 504 LGapResolver::LGapResolver(const ZoneList<LMoveOperands>* moves, | |
| 505 LOperand* marker_operand) | |
| 506 : nodes_(4), | |
| 507 identified_cycles_(4), | |
| 508 result_(4), | |
| 509 marker_operand_(marker_operand), | |
| 510 next_visited_id_(0) { | |
| 511 for (int i = 0; i < moves->length(); ++i) { | |
| 512 LMoveOperands move = moves->at(i); | |
| 513 if (!move.IsRedundant()) RegisterMove(move); | |
| 514 } | |
| 515 } | |
| 516 | |
| 517 | |
| 518 const ZoneList<LMoveOperands>* LGapResolver::ResolveInReverseOrder() { | |
| 519 for (int i = 0; i < identified_cycles_.length(); ++i) { | |
| 520 ResolveCycle(identified_cycles_[i]); | |
| 521 } | |
| 522 | |
| 523 int unresolved_nodes; | |
| 524 do { | |
| 525 unresolved_nodes = 0; | |
| 526 for (int j = 0; j < nodes_.length(); j++) { | |
| 527 LGapNode* node = nodes_[j]; | |
| 528 if (!node->IsResolved() && node->assigned_from()->IsResolved()) { | |
| 529 AddResultMove(node->assigned_from(), node); | |
| 530 node->MarkResolved(); | |
| 531 } | |
| 532 if (!node->IsResolved()) ++unresolved_nodes; | |
| 533 } | |
| 534 } while (unresolved_nodes > 0); | |
| 535 return &result_; | |
| 536 } | |
| 537 | |
| 538 | |
| 539 void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) { | |
| 540 AddResultMove(from->operand(), to->operand()); | |
| 541 } | |
| 542 | |
| 543 | |
| 544 void LGapResolver::AddResultMove(LOperand* from, LOperand* to) { | |
| 545 result_.Add(LMoveOperands(from, to)); | |
| 546 } | |
| 547 | |
| 548 | |
| 549 void LGapResolver::ResolveCycle(LGapNode* start) { | |
| 550 ZoneList<LOperand*> circle_operands(8); | |
| 551 circle_operands.Add(marker_operand_); | |
| 552 LGapNode* cur = start; | |
| 553 do { | |
| 554 cur->MarkResolved(); | |
| 555 circle_operands.Add(cur->operand()); | |
| 556 cur = cur->assigned_from(); | |
| 557 } while (cur != start); | |
| 558 circle_operands.Add(marker_operand_); | |
| 559 | |
| 560 for (int i = circle_operands.length() - 1; i > 0; --i) { | |
| 561 LOperand* from = circle_operands[i]; | |
| 562 LOperand* to = circle_operands[i - 1]; | |
| 563 AddResultMove(from, to); | |
| 564 } | |
| 565 } | |
| 566 | |
| 567 | |
| 568 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) { | |
| 569 ASSERT(a != b); | |
| 570 LGapNode* cur = a; | |
| 571 while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) { | |
| 572 cur->set_visited_id(visited_id); | |
| 573 cur = cur->assigned_from(); | |
| 574 } | |
| 575 | |
| 576 return cur == b; | |
| 577 } | |
| 578 | |
| 579 | |
| 580 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) { | |
| 581 ASSERT(a != b); | |
| 582 return CanReach(a, b, next_visited_id_++); | |
| 583 } | |
| 584 | |
| 585 | |
| 586 void LGapResolver::RegisterMove(LMoveOperands move) { | |
| 587 if (move.from()->IsConstantOperand()) { | |
| 588 // Constant moves should be last in the machine code. Therefore add them | |
| 589 // first to the result set. | |
| 590 AddResultMove(move.from(), move.to()); | |
| 591 } else { | |
| 592 LGapNode* from = LookupNode(move.from()); | |
| 593 LGapNode* to = LookupNode(move.to()); | |
| 594 if (to->IsAssigned() && to->assigned_from() == from) { | |
| 595 move.Eliminate(); | |
| 596 return; | |
| 597 } | |
| 598 ASSERT(!to->IsAssigned()); | |
| 599 if (CanReach(from, to)) { | |
| 600 // This introduces a circle. Save. | |
| 601 identified_cycles_.Add(from); | |
| 602 } | |
| 603 to->set_assigned_from(from); | |
| 604 } | |
| 605 } | |
| 606 | |
| 607 | |
| 608 LGapNode* LGapResolver::LookupNode(LOperand* operand) { | |
| 609 for (int i = 0; i < nodes_.length(); ++i) { | |
| 610 if (nodes_[i]->operand()->Equals(operand)) return nodes_[i]; | |
| 611 } | |
| 612 | |
| 613 // No node found => create a new one. | |
| 614 LGapNode* result = new LGapNode(operand); | |
| 615 nodes_.Add(result); | |
| 616 return result; | |
| 617 } | |
| 618 | |
| 619 | |
| 620 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const { | 443 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const { |
| 621 return HConstant::cast(graph_->LookupValue(operand->index()))->handle(); | 444 return HConstant::cast(graph_->LookupValue(operand->index()))->handle(); |
| 622 } | 445 } |
| 623 | 446 |
| 624 | 447 |
| 625 Representation LChunk::LookupLiteralRepresentation( | 448 Representation LChunk::LookupLiteralRepresentation( |
| 626 LConstantOperand* operand) const { | 449 LConstantOperand* operand) const { |
| 627 return graph_->LookupValue(operand->index())->representation(); | 450 return graph_->LookupValue(operand->index())->representation(); |
| 628 } | 451 } |
| 629 | 452 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { | 568 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { |
| 746 if (value->EmitAtUses()) { | 569 if (value->EmitAtUses()) { |
| 747 HInstruction* instr = HInstruction::cast(value); | 570 HInstruction* instr = HInstruction::cast(value); |
| 748 VisitInstruction(instr); | 571 VisitInstruction(instr); |
| 749 } | 572 } |
| 750 allocator_->RecordUse(value, operand); | 573 allocator_->RecordUse(value, operand); |
| 751 return operand; | 574 return operand; |
| 752 } | 575 } |
| 753 | 576 |
| 754 | 577 |
| 755 LInstruction* LChunkBuilder::Define(LInstruction* instr) { | 578 template<int I, int T> |
| 579 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr, |
| 580 LUnallocated* result) { |
| 581 allocator_->RecordDefinition(current_instruction_, result); |
| 582 instr->set_result(result); |
| 583 return instr; |
| 584 } |
| 585 |
| 586 |
| 587 template<int I, int T> |
| 588 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) { |
| 756 return Define(instr, new LUnallocated(LUnallocated::NONE)); | 589 return Define(instr, new LUnallocated(LUnallocated::NONE)); |
| 757 } | 590 } |
| 758 | 591 |
| 759 | 592 |
| 760 LInstruction* LChunkBuilder::DefineAsRegister(LInstruction* instr) { | 593 template<int I, int T> |
| 594 LInstruction* LChunkBuilder::DefineAsRegister( |
| 595 LTemplateInstruction<1, I, T>* instr) { |
| 761 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); | 596 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); |
| 762 } | 597 } |
| 763 | 598 |
| 764 | 599 |
| 765 LInstruction* LChunkBuilder::DefineAsSpilled(LInstruction* instr, int index) { | 600 template<int I, int T> |
| 601 LInstruction* LChunkBuilder::DefineAsSpilled( |
| 602 LTemplateInstruction<1, I, T>* instr, |
| 603 int index) { |
| 766 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index)); | 604 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index)); |
| 767 } | 605 } |
| 768 | 606 |
| 769 | 607 |
| 770 LInstruction* LChunkBuilder::DefineSameAsAny(LInstruction* instr) { | 608 template<int I, int T> |
| 771 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_ANY_INPUT)); | 609 LInstruction* LChunkBuilder::DefineSameAsFirst( |
| 772 } | 610 LTemplateInstruction<1, I, T>* instr) { |
| 773 | |
| 774 | |
| 775 LInstruction* LChunkBuilder::DefineSameAsFirst(LInstruction* instr) { | |
| 776 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); | 611 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); |
| 777 } | 612 } |
| 778 | 613 |
| 779 | 614 |
| 780 LInstruction* LChunkBuilder::DefineFixed(LInstruction* instr, Register reg) { | 615 template<int I, int T> |
| 616 LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr, |
| 617 Register reg) { |
| 781 return Define(instr, ToUnallocated(reg)); | 618 return Define(instr, ToUnallocated(reg)); |
| 782 } | 619 } |
| 783 | 620 |
| 784 | 621 |
| 785 LInstruction* LChunkBuilder::DefineFixedDouble(LInstruction* instr, | 622 template<int I, int T> |
| 786 XMMRegister reg) { | 623 LInstruction* LChunkBuilder::DefineFixedDouble( |
| 624 LTemplateInstruction<1, I, T>* instr, |
| 625 XMMRegister reg) { |
| 787 return Define(instr, ToUnallocated(reg)); | 626 return Define(instr, ToUnallocated(reg)); |
| 788 } | 627 } |
| 789 | 628 |
| 790 | 629 |
| 791 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { | 630 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { |
| 792 HEnvironment* hydrogen_env = current_block_->last_environment(); | 631 HEnvironment* hydrogen_env = current_block_->last_environment(); |
| 793 instr->set_environment(CreateEnvironment(hydrogen_env)); | 632 instr->set_environment(CreateEnvironment(hydrogen_env)); |
| 794 return instr; | 633 return instr; |
| 795 } | 634 } |
| 796 | 635 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 bool needs_environment = | 670 bool needs_environment = |
| 832 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); | 671 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); |
| 833 if (needs_environment && !instr->HasEnvironment()) { | 672 if (needs_environment && !instr->HasEnvironment()) { |
| 834 instr = AssignEnvironment(instr); | 673 instr = AssignEnvironment(instr); |
| 835 } | 674 } |
| 836 | 675 |
| 837 return instr; | 676 return instr; |
| 838 } | 677 } |
| 839 | 678 |
| 840 | 679 |
| 680 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { |
| 681 allocator_->MarkAsSaveDoubles(); |
| 682 return instr; |
| 683 } |
| 684 |
| 685 |
| 841 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { | 686 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
| 842 ASSERT(!instr->HasPointerMap()); | 687 ASSERT(!instr->HasPointerMap()); |
| 843 instr->set_pointer_map(new LPointerMap(position_)); | 688 instr->set_pointer_map(new LPointerMap(position_)); |
| 844 return instr; | 689 return instr; |
| 845 } | 690 } |
| 846 | 691 |
| 847 | 692 |
| 848 LInstruction* LChunkBuilder::Define(LInstruction* instr, LUnallocated* result) { | |
| 849 allocator_->RecordDefinition(current_instruction_, result); | |
| 850 instr->set_result(result); | |
| 851 return instr; | |
| 852 } | |
| 853 | |
| 854 | |
| 855 LOperand* LChunkBuilder::Temp() { | |
| 856 LUnallocated* operand = new LUnallocated(LUnallocated::NONE); | |
| 857 allocator_->RecordTemporary(operand); | |
| 858 return operand; | |
| 859 } | |
| 860 | |
| 861 | |
| 862 LUnallocated* LChunkBuilder::TempRegister() { | 693 LUnallocated* LChunkBuilder::TempRegister() { |
| 863 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER); | 694 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER); |
| 864 allocator_->RecordTemporary(operand); | 695 allocator_->RecordTemporary(operand); |
| 865 return operand; | 696 return operand; |
| 866 } | 697 } |
| 867 | 698 |
| 868 | 699 |
| 869 LOperand* LChunkBuilder::FixedTemp(Register reg) { | 700 LOperand* LChunkBuilder::FixedTemp(Register reg) { |
| 870 LUnallocated* operand = ToUnallocated(reg); | 701 LUnallocated* operand = ToUnallocated(reg); |
| 871 allocator_->RecordTemporary(operand); | 702 allocator_->RecordTemporary(operand); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 927 bool can_truncate = true; | 758 bool can_truncate = true; |
| 928 for (int i = 0; i < instr->uses()->length(); i++) { | 759 for (int i = 0; i < instr->uses()->length(); i++) { |
| 929 if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) { | 760 if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) { |
| 930 can_truncate = false; | 761 can_truncate = false; |
| 931 break; | 762 break; |
| 932 } | 763 } |
| 933 } | 764 } |
| 934 can_deopt = !can_truncate; | 765 can_deopt = !can_truncate; |
| 935 } | 766 } |
| 936 | 767 |
| 937 LInstruction* result = | 768 LShiftI* result = new LShiftI(op, left, right, can_deopt); |
| 938 DefineSameAsFirst(new LShiftI(op, left, right, can_deopt)); | 769 return can_deopt |
| 939 if (can_deopt) AssignEnvironment(result); | 770 ? AssignEnvironment(DefineSameAsFirst(result)) |
| 940 return result; | 771 : DefineSameAsFirst(result); |
| 941 } | 772 } |
| 942 | 773 |
| 943 | 774 |
| 944 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 775 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
| 945 HArithmeticBinaryOperation* instr) { | 776 HArithmeticBinaryOperation* instr) { |
| 946 ASSERT(instr->representation().IsDouble()); | 777 ASSERT(instr->representation().IsDouble()); |
| 947 ASSERT(instr->left()->representation().IsDouble()); | 778 ASSERT(instr->left()->representation().IsDouble()); |
| 948 ASSERT(instr->right()->representation().IsDouble()); | 779 ASSERT(instr->right()->representation().IsDouble()); |
| 949 LOperand* left = UseRegisterAtStart(instr->left()); | 780 LOperand* left = UseRegisterAtStart(instr->left()); |
| 950 LOperand* right = UseRegisterAtStart(instr->right()); | 781 LOperand* right = UseRegisterAtStart(instr->right()); |
| 951 LArithmeticD* result = new LArithmeticD(op, left, right); | 782 LArithmeticD* result = new LArithmeticD(op, left, right); |
| 952 return DefineSameAsFirst(result); | 783 return DefineSameAsFirst(result); |
| 953 } | 784 } |
| 954 | 785 |
| 955 | 786 |
| 956 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 787 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 957 HArithmeticBinaryOperation* instr) { | 788 HArithmeticBinaryOperation* instr) { |
| 958 ASSERT(op == Token::ADD || | 789 ASSERT(op == Token::ADD || |
| 959 op == Token::DIV || | 790 op == Token::DIV || |
| 960 op == Token::MOD || | 791 op == Token::MOD || |
| 961 op == Token::MUL || | 792 op == Token::MUL || |
| 962 op == Token::SUB); | 793 op == Token::SUB); |
| 963 HValue* left = instr->left(); | 794 HValue* left = instr->left(); |
| 964 HValue* right = instr->right(); | 795 HValue* right = instr->right(); |
| 965 ASSERT(left->representation().IsTagged()); | 796 ASSERT(left->representation().IsTagged()); |
| 966 ASSERT(right->representation().IsTagged()); | 797 ASSERT(right->representation().IsTagged()); |
| 967 LOperand* left_operand = UseFixed(left, edx); | 798 LOperand* left_operand = UseFixed(left, edx); |
| 968 LOperand* right_operand = UseFixed(right, eax); | 799 LOperand* right_operand = UseFixed(right, eax); |
| 969 LInstruction* result = new LArithmeticT(op, left_operand, right_operand); | 800 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand); |
| 970 return MarkAsCall(DefineFixed(result, eax), instr); | 801 return MarkAsCall(DefineFixed(result, eax), instr); |
| 971 } | 802 } |
| 972 | 803 |
| 973 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { | 804 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { |
| 974 ASSERT(is_building()); | 805 ASSERT(is_building()); |
| 975 current_block_ = block; | 806 current_block_ = block; |
| 976 next_block_ = next_block; | 807 next_block_ = next_block; |
| 977 if (block->IsStartBlock()) { | 808 if (block->IsStartBlock()) { |
| 978 block->UpdateEnvironment(graph_->start_environment()); | 809 block->UpdateEnvironment(graph_->start_environment()); |
| 979 argument_count_ = 0; | 810 argument_count_ = 0; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1009 last_environment->SetValueAt(block->deleted_phis()->at(i), | 840 last_environment->SetValueAt(block->deleted_phis()->at(i), |
| 1010 graph_->GetConstantUndefined()); | 841 graph_->GetConstantUndefined()); |
| 1011 } | 842 } |
| 1012 block->UpdateEnvironment(last_environment); | 843 block->UpdateEnvironment(last_environment); |
| 1013 // Pick up the outgoing argument count of one of the predecessors. | 844 // Pick up the outgoing argument count of one of the predecessors. |
| 1014 argument_count_ = pred->argument_count(); | 845 argument_count_ = pred->argument_count(); |
| 1015 } | 846 } |
| 1016 HInstruction* current = block->first(); | 847 HInstruction* current = block->first(); |
| 1017 int start = chunk_->instructions()->length(); | 848 int start = chunk_->instructions()->length(); |
| 1018 while (current != NULL && !is_aborted()) { | 849 while (current != NULL && !is_aborted()) { |
| 1019 if (FLAG_trace_environment) { | |
| 1020 PrintF("Process instruction %d\n", current->id()); | |
| 1021 } | |
| 1022 // Code for constants in registers is generated lazily. | 850 // Code for constants in registers is generated lazily. |
| 1023 if (!current->EmitAtUses()) { | 851 if (!current->EmitAtUses()) { |
| 1024 VisitInstruction(current); | 852 VisitInstruction(current); |
| 1025 } | 853 } |
| 1026 current = current->next(); | 854 current = current->next(); |
| 1027 } | 855 } |
| 1028 int end = chunk_->instructions()->length() - 1; | 856 int end = chunk_->instructions()->length() - 1; |
| 1029 if (end >= start) { | 857 if (end >= start) { |
| 1030 block->set_first_instruction_index(start); | 858 block->set_first_instruction_index(start); |
| 1031 block->set_last_instruction_index(end); | 859 block->set_last_instruction_index(end); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1059 int index = chunk_->AddInstruction(instr, current_block_); | 887 int index = chunk_->AddInstruction(instr, current_block_); |
| 1060 allocator_->SummarizeInstruction(index); | 888 allocator_->SummarizeInstruction(index); |
| 1061 } else { | 889 } else { |
| 1062 // This instruction should be omitted. | 890 // This instruction should be omitted. |
| 1063 allocator_->OmitInstruction(); | 891 allocator_->OmitInstruction(); |
| 1064 } | 892 } |
| 1065 current_instruction_ = old_current; | 893 current_instruction_ = old_current; |
| 1066 } | 894 } |
| 1067 | 895 |
| 1068 | 896 |
| 1069 void LEnvironment::WriteTranslation(LCodeGen* cgen, | |
| 1070 Translation* translation) const { | |
| 1071 if (this == NULL) return; | |
| 1072 | |
| 1073 // The translation includes one command per value in the environment. | |
| 1074 int translation_size = values()->length(); | |
| 1075 // The output frame height does not include the parameters. | |
| 1076 int height = translation_size - parameter_count(); | |
| 1077 | |
| 1078 outer()->WriteTranslation(cgen, translation); | |
| 1079 int closure_id = cgen->DefineDeoptimizationLiteral(closure()); | |
| 1080 translation->BeginFrame(ast_id(), closure_id, height); | |
| 1081 for (int i = 0; i < translation_size; ++i) { | |
| 1082 LOperand* value = values()->at(i); | |
| 1083 // spilled_registers_ and spilled_double_registers_ are either | |
| 1084 // both NULL or both set. | |
| 1085 if (spilled_registers_ != NULL && value != NULL) { | |
| 1086 if (value->IsRegister() && | |
| 1087 spilled_registers_[value->index()] != NULL) { | |
| 1088 translation->MarkDuplicate(); | |
| 1089 cgen->AddToTranslation(translation, | |
| 1090 spilled_registers_[value->index()], | |
| 1091 HasTaggedValueAt(i)); | |
| 1092 } else if (value->IsDoubleRegister() && | |
| 1093 spilled_double_registers_[value->index()] != NULL) { | |
| 1094 translation->MarkDuplicate(); | |
| 1095 cgen->AddToTranslation(translation, | |
| 1096 spilled_double_registers_[value->index()], | |
| 1097 false); | |
| 1098 } | |
| 1099 } | |
| 1100 | |
| 1101 cgen->AddToTranslation(translation, value, HasTaggedValueAt(i)); | |
| 1102 } | |
| 1103 } | |
| 1104 | |
| 1105 | |
| 1106 void LEnvironment::PrintTo(StringStream* stream) const { | |
| 1107 stream->Add("[id=%d|", ast_id()); | |
| 1108 stream->Add("[parameters=%d|", parameter_count()); | |
| 1109 stream->Add("[arguments_stack_height=%d|", arguments_stack_height()); | |
| 1110 for (int i = 0; i < values_.length(); ++i) { | |
| 1111 if (i != 0) stream->Add(";"); | |
| 1112 if (values_[i] == NULL) { | |
| 1113 stream->Add("[hole]"); | |
| 1114 } else { | |
| 1115 values_[i]->PrintTo(stream); | |
| 1116 } | |
| 1117 } | |
| 1118 stream->Add("]"); | |
| 1119 } | |
| 1120 | |
| 1121 | |
| 1122 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { | 897 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { |
| 1123 if (hydrogen_env == NULL) return NULL; | 898 if (hydrogen_env == NULL) return NULL; |
| 1124 | 899 |
| 1125 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); | 900 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); |
| 1126 int ast_id = hydrogen_env->ast_id(); | 901 int ast_id = hydrogen_env->ast_id(); |
| 1127 ASSERT(ast_id != AstNode::kNoNumber); | 902 ASSERT(ast_id != AstNode::kNoNumber); |
| 1128 int value_count = hydrogen_env->values()->length(); | 903 int value_count = hydrogen_env->length(); |
| 1129 LEnvironment* result = new LEnvironment(hydrogen_env->closure(), | 904 LEnvironment* result = new LEnvironment(hydrogen_env->closure(), |
| 1130 ast_id, | 905 ast_id, |
| 1131 hydrogen_env->parameter_count(), | 906 hydrogen_env->parameter_count(), |
| 1132 argument_count_, | 907 argument_count_, |
| 1133 value_count, | 908 value_count, |
| 1134 outer); | 909 outer); |
| 1135 int argument_index = 0; | 910 int argument_index = 0; |
| 1136 for (int i = 0; i < value_count; ++i) { | 911 for (int i = 0; i < value_count; ++i) { |
| 1137 HValue* value = hydrogen_env->values()->at(i); | 912 HValue* value = hydrogen_env->values()->at(i); |
| 1138 LOperand* op = NULL; | 913 LOperand* op = NULL; |
| 1139 if (value->IsArgumentsObject()) { | 914 if (value->IsArgumentsObject()) { |
| 1140 op = NULL; | 915 op = NULL; |
| 1141 } else if (value->IsPushArgument()) { | 916 } else if (value->IsPushArgument()) { |
| 1142 op = new LArgument(argument_index++); | 917 op = new LArgument(argument_index++); |
| 1143 } else { | 918 } else { |
| 1144 op = UseOrConstant(value); | 919 op = UseOrConstant(value); |
| 1145 if (op->IsUnallocated()) { | 920 if (op->IsUnallocated()) { |
| 1146 LUnallocated* unalloc = LUnallocated::cast(op); | 921 LUnallocated* unalloc = LUnallocated::cast(op); |
| 1147 unalloc->set_policy(LUnallocated::ANY); | 922 unalloc->set_policy(LUnallocated::ANY); |
| 1148 } | 923 } |
| 1149 } | 924 } |
| 1150 result->AddValue(op, value->representation()); | 925 result->AddValue(op, value->representation()); |
| 1151 } | 926 } |
| 1152 | 927 |
| 1153 return result; | 928 return result; |
| 1154 } | 929 } |
| 1155 | 930 |
| 1156 | 931 |
| 1157 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 932 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 1158 LInstruction* result = new LGoto(instr->FirstSuccessor()->block_id(), | 933 LGoto* result = new LGoto(instr->FirstSuccessor()->block_id(), |
| 1159 instr->include_stack_check()); | 934 instr->include_stack_check()); |
| 1160 if (instr->include_stack_check()) result = AssignPointerMap(result); | 935 return (instr->include_stack_check()) |
| 1161 return result; | 936 ? AssignPointerMap(result) |
| 937 : result; |
| 1162 } | 938 } |
| 1163 | 939 |
| 1164 | 940 |
| 1165 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 941 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
| 1166 HValue* v = instr->value(); | 942 HValue* v = instr->value(); |
| 1167 HBasicBlock* first = instr->FirstSuccessor(); | 943 HBasicBlock* first = instr->FirstSuccessor(); |
| 1168 HBasicBlock* second = instr->SecondSuccessor(); | 944 HBasicBlock* second = instr->SecondSuccessor(); |
| 1169 ASSERT(first != NULL && second != NULL); | 945 ASSERT(first != NULL && second != NULL); |
| 1170 int first_id = first->block_id(); | 946 int first_id = first->block_id(); |
| 1171 int second_id = second->block_id(); | 947 int second_id = second->block_id(); |
| 1172 | 948 |
| 1173 if (v->EmitAtUses()) { | 949 if (v->EmitAtUses()) { |
| 1174 if (v->IsClassOfTest()) { | 950 if (v->IsClassOfTest()) { |
| 1175 HClassOfTest* compare = HClassOfTest::cast(v); | 951 HClassOfTest* compare = HClassOfTest::cast(v); |
| 1176 ASSERT(compare->value()->representation().IsTagged()); | 952 ASSERT(compare->value()->representation().IsTagged()); |
| 1177 | 953 |
| 1178 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), | 954 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), |
| 1179 TempRegister(), | 955 TempRegister(), |
| 1180 TempRegister(), | 956 TempRegister(), |
| 1181 first_id, | 957 first_id, |
| 1182 second_id); | 958 second_id); |
| 1183 } else if (v->IsCompare()) { | 959 } else if (v->IsCompare()) { |
| 1184 HCompare* compare = HCompare::cast(v); | 960 HCompare* compare = HCompare::cast(v); |
| 1185 Token::Value op = compare->token(); | 961 Token::Value op = compare->token(); |
| 1186 HValue* left = compare->left(); | 962 HValue* left = compare->left(); |
| 1187 HValue* right = compare->right(); | 963 HValue* right = compare->right(); |
| 1188 if (left->representation().IsInteger32()) { | 964 Representation r = compare->GetInputRepresentation(); |
| 965 if (r.IsInteger32()) { |
| 966 ASSERT(left->representation().IsInteger32()); |
| 1189 ASSERT(right->representation().IsInteger32()); | 967 ASSERT(right->representation().IsInteger32()); |
| 1190 return new LCmpIDAndBranch(op, | 968 |
| 1191 UseRegisterAtStart(left), | 969 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 1192 UseOrConstantAtStart(right), | 970 UseOrConstantAtStart(right), |
| 1193 first_id, | 971 first_id, |
| 1194 second_id, | 972 second_id); |
| 1195 false); | 973 } else if (r.IsDouble()) { |
| 1196 } else if (left->representation().IsDouble()) { | 974 ASSERT(left->representation().IsDouble()); |
| 1197 ASSERT(right->representation().IsDouble()); | 975 ASSERT(right->representation().IsDouble()); |
| 1198 return new LCmpIDAndBranch(op, | 976 |
| 1199 UseRegisterAtStart(left), | 977 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 1200 UseRegisterAtStart(right), | 978 UseRegisterAtStart(right), |
| 1201 first_id, | 979 first_id, |
| 1202 second_id, | 980 second_id); |
| 1203 true); | |
| 1204 } else { | 981 } else { |
| 1205 ASSERT(left->representation().IsTagged()); | 982 ASSERT(left->representation().IsTagged()); |
| 1206 ASSERT(right->representation().IsTagged()); | 983 ASSERT(right->representation().IsTagged()); |
| 1207 bool reversed = op == Token::GT || op == Token::LTE; | 984 bool reversed = op == Token::GT || op == Token::LTE; |
| 1208 LOperand* left_operand = UseFixed(left, reversed ? eax : edx); | 985 LOperand* left_operand = UseFixed(left, reversed ? eax : edx); |
| 1209 LOperand* right_operand = UseFixed(right, reversed ? edx : eax); | 986 LOperand* right_operand = UseFixed(right, reversed ? edx : eax); |
| 1210 LInstruction* result = new LCmpTAndBranch(left_operand, | 987 LCmpTAndBranch* result = new LCmpTAndBranch(left_operand, |
| 1211 right_operand, | 988 right_operand, |
| 1212 first_id, | 989 first_id, |
| 1213 second_id); | 990 second_id); |
| 1214 return MarkAsCall(result, instr); | 991 return MarkAsCall(result, instr); |
| 1215 } | 992 } |
| 1216 } else if (v->IsIsSmi()) { | 993 } else if (v->IsIsSmi()) { |
| 1217 HIsSmi* compare = HIsSmi::cast(v); | 994 HIsSmi* compare = HIsSmi::cast(v); |
| 1218 ASSERT(compare->value()->representation().IsTagged()); | 995 ASSERT(compare->value()->representation().IsTagged()); |
| 1219 | 996 |
| 1220 return new LIsSmiAndBranch(Use(compare->value()), | 997 return new LIsSmiAndBranch(Use(compare->value()), |
| 1221 first_id, | 998 first_id, |
| 1222 second_id); | 999 second_id); |
| 1223 } else if (v->IsHasInstanceType()) { | 1000 } else if (v->IsHasInstanceType()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1234 | 1011 |
| 1235 return new LHasCachedArrayIndexAndBranch( | 1012 return new LHasCachedArrayIndexAndBranch( |
| 1236 UseRegisterAtStart(compare->value()), first_id, second_id); | 1013 UseRegisterAtStart(compare->value()), first_id, second_id); |
| 1237 } else if (v->IsIsNull()) { | 1014 } else if (v->IsIsNull()) { |
| 1238 HIsNull* compare = HIsNull::cast(v); | 1015 HIsNull* compare = HIsNull::cast(v); |
| 1239 ASSERT(compare->value()->representation().IsTagged()); | 1016 ASSERT(compare->value()->representation().IsTagged()); |
| 1240 | 1017 |
| 1241 // We only need a temp register for non-strict compare. | 1018 // We only need a temp register for non-strict compare. |
| 1242 LOperand* temp = compare->is_strict() ? NULL : TempRegister(); | 1019 LOperand* temp = compare->is_strict() ? NULL : TempRegister(); |
| 1243 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()), | 1020 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()), |
| 1244 compare->is_strict(), | |
| 1245 temp, | 1021 temp, |
| 1246 first_id, | 1022 first_id, |
| 1247 second_id); | 1023 second_id); |
| 1248 } else if (v->IsIsObject()) { | 1024 } else if (v->IsIsObject()) { |
| 1249 HIsObject* compare = HIsObject::cast(v); | 1025 HIsObject* compare = HIsObject::cast(v); |
| 1250 ASSERT(compare->value()->representation().IsTagged()); | 1026 ASSERT(compare->value()->representation().IsTagged()); |
| 1251 | 1027 |
| 1252 LOperand* temp1 = TempRegister(); | 1028 LOperand* temp1 = TempRegister(); |
| 1253 LOperand* temp2 = TempRegister(); | 1029 LOperand* temp2 = TempRegister(); |
| 1254 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), | 1030 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), |
| 1255 temp1, | 1031 temp1, |
| 1256 temp2, | 1032 temp2, |
| 1257 first_id, | 1033 first_id, |
| 1258 second_id); | 1034 second_id); |
| 1259 } else if (v->IsCompareJSObjectEq()) { | 1035 } else if (v->IsCompareJSObjectEq()) { |
| 1260 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); | 1036 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); |
| 1261 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), | 1037 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), |
| 1262 UseRegisterAtStart(compare->right()), | 1038 UseRegisterAtStart(compare->right()), |
| 1263 first_id, | 1039 first_id, |
| 1264 second_id); | 1040 second_id); |
| 1265 } else if (v->IsInstanceOf()) { | 1041 } else if (v->IsInstanceOf()) { |
| 1266 HInstanceOf* instance_of = HInstanceOf::cast(v); | 1042 HInstanceOf* instance_of = HInstanceOf::cast(v); |
| 1267 LInstruction* result = | 1043 LInstanceOfAndBranch* result = |
| 1268 new LInstanceOfAndBranch(UseFixed(instance_of->left(), eax), | 1044 new LInstanceOfAndBranch( |
| 1269 UseFixed(instance_of->right(), edx), | 1045 UseFixed(instance_of->left(), InstanceofStub::left()), |
| 1270 first_id, | 1046 UseFixed(instance_of->right(), InstanceofStub::right()), |
| 1271 second_id); | 1047 first_id, |
| 1048 second_id); |
| 1272 return MarkAsCall(result, instr); | 1049 return MarkAsCall(result, instr); |
| 1273 } else if (v->IsTypeofIs()) { | 1050 } else if (v->IsTypeofIs()) { |
| 1274 HTypeofIs* typeof_is = HTypeofIs::cast(v); | 1051 HTypeofIs* typeof_is = HTypeofIs::cast(v); |
| 1275 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()), | 1052 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()), |
| 1276 first_id, | 1053 first_id, |
| 1277 second_id); | 1054 second_id); |
| 1278 } else { | 1055 } else { |
| 1279 if (v->IsConstant()) { | 1056 if (v->IsConstant()) { |
| 1280 if (HConstant::cast(v)->handle()->IsTrue()) { | 1057 if (HConstant::cast(v)->handle()->IsTrue()) { |
| 1281 return new LGoto(first_id); | 1058 return new LGoto(first_id); |
| 1282 } else if (HConstant::cast(v)->handle()->IsFalse()) { | 1059 } else if (HConstant::cast(v)->handle()->IsFalse()) { |
| 1283 return new LGoto(second_id); | 1060 return new LGoto(second_id); |
| 1284 } | 1061 } |
| 1285 } | 1062 } |
| 1286 Abort("Undefined compare before branch"); | 1063 Abort("Undefined compare before branch"); |
| 1287 return NULL; | 1064 return NULL; |
| 1288 } | 1065 } |
| 1289 } | 1066 } |
| 1290 return new LBranch(UseRegisterAtStart(v), first_id, second_id); | 1067 return new LBranch(UseRegisterAtStart(v), first_id, second_id); |
| 1291 } | 1068 } |
| 1292 | 1069 |
| 1293 | 1070 |
| 1294 LInstruction* LChunkBuilder::DoCompareMapAndBranch( | 1071 LInstruction* LChunkBuilder::DoCompareMapAndBranch( |
| 1295 HCompareMapAndBranch* instr) { | 1072 HCompareMapAndBranch* instr) { |
| 1296 ASSERT(instr->value()->representation().IsTagged()); | 1073 ASSERT(instr->value()->representation().IsTagged()); |
| 1297 LOperand* value = UseRegisterAtStart(instr->value()); | 1074 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1298 HBasicBlock* first = instr->FirstSuccessor(); | 1075 return new LCmpMapAndBranch(value); |
| 1299 HBasicBlock* second = instr->SecondSuccessor(); | |
| 1300 return new LCmpMapAndBranch(value, | |
| 1301 instr->map(), | |
| 1302 first->block_id(), | |
| 1303 second->block_id()); | |
| 1304 } | 1076 } |
| 1305 | 1077 |
| 1306 | 1078 |
| 1307 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { | 1079 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { |
| 1308 return DefineAsRegister(new LArgumentsLength(Use(length->value()))); | 1080 return DefineAsRegister(new LArgumentsLength(Use(length->value()))); |
| 1309 } | 1081 } |
| 1310 | 1082 |
| 1311 | 1083 |
| 1312 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { | 1084 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { |
| 1313 return DefineAsRegister(new LArgumentsElements); | 1085 return DefineAsRegister(new LArgumentsElements); |
| 1314 } | 1086 } |
| 1315 | 1087 |
| 1316 | 1088 |
| 1317 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { | 1089 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { |
| 1318 LInstruction* result = | 1090 LInstanceOf* result = |
| 1319 new LInstanceOf(UseFixed(instr->left(), eax), | 1091 new LInstanceOf(UseFixed(instr->left(), InstanceofStub::left()), |
| 1320 UseFixed(instr->right(), edx)); | 1092 UseFixed(instr->right(), InstanceofStub::right())); |
| 1321 return MarkAsCall(DefineFixed(result, eax), instr); | 1093 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1322 } | 1094 } |
| 1323 | 1095 |
| 1324 | 1096 |
| 1097 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
| 1098 HInstanceOfKnownGlobal* instr) { |
| 1099 LInstanceOfKnownGlobal* result = |
| 1100 new LInstanceOfKnownGlobal( |
| 1101 UseFixed(instr->value(), InstanceofStub::left()), |
| 1102 FixedTemp(edi)); |
| 1103 MarkAsSaveDoubles(result); |
| 1104 return AssignEnvironment(AssignPointerMap(DefineFixed(result, eax))); |
| 1105 } |
| 1106 |
| 1107 |
| 1325 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 1108 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
| 1326 LOperand* function = UseFixed(instr->function(), edi); | 1109 LOperand* function = UseFixed(instr->function(), edi); |
| 1327 LOperand* receiver = UseFixed(instr->receiver(), eax); | 1110 LOperand* receiver = UseFixed(instr->receiver(), eax); |
| 1328 LOperand* length = UseRegisterAtStart(instr->length()); | 1111 LOperand* length = UseRegisterAtStart(instr->length()); |
| 1329 LOperand* elements = UseRegisterAtStart(instr->elements()); | 1112 LOperand* elements = UseRegisterAtStart(instr->elements()); |
| 1330 LInstruction* result = new LApplyArguments(function, | 1113 LApplyArguments* result = new LApplyArguments(function, |
| 1331 receiver, | 1114 receiver, |
| 1332 length, | 1115 length, |
| 1333 elements); | 1116 elements); |
| 1334 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY); | 1117 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1335 } | 1118 } |
| 1336 | 1119 |
| 1337 | 1120 |
| 1338 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { | 1121 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
| 1339 ++argument_count_; | 1122 ++argument_count_; |
| 1340 LOperand* argument = UseOrConstant(instr->argument()); | 1123 LOperand* argument = UseOrConstant(instr->argument()); |
| 1341 return new LPushArgument(argument); | 1124 return new LPushArgument(argument); |
| 1342 } | 1125 } |
| 1343 | 1126 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1356 HCallConstantFunction* instr) { | 1139 HCallConstantFunction* instr) { |
| 1357 argument_count_ -= instr->argument_count(); | 1140 argument_count_ -= instr->argument_count(); |
| 1358 return MarkAsCall(DefineFixed(new LCallConstantFunction, eax), instr); | 1141 return MarkAsCall(DefineFixed(new LCallConstantFunction, eax), instr); |
| 1359 } | 1142 } |
| 1360 | 1143 |
| 1361 | 1144 |
| 1362 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 1145 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1363 BuiltinFunctionId op = instr->op(); | 1146 BuiltinFunctionId op = instr->op(); |
| 1364 if (op == kMathLog || op == kMathSin || op == kMathCos) { | 1147 if (op == kMathLog || op == kMathSin || op == kMathCos) { |
| 1365 LOperand* input = UseFixedDouble(instr->value(), xmm1); | 1148 LOperand* input = UseFixedDouble(instr->value(), xmm1); |
| 1366 LInstruction* result = new LUnaryMathOperation(input); | 1149 LUnaryMathOperation* result = new LUnaryMathOperation(input); |
| 1367 return MarkAsCall(DefineFixedDouble(result, xmm1), instr); | 1150 return MarkAsCall(DefineFixedDouble(result, xmm1), instr); |
| 1368 } else { | 1151 } else { |
| 1369 LOperand* input = UseRegisterAtStart(instr->value()); | 1152 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1370 LInstruction* result = new LUnaryMathOperation(input); | 1153 LUnaryMathOperation* result = new LUnaryMathOperation(input); |
| 1371 switch (op) { | 1154 switch (op) { |
| 1372 case kMathAbs: | 1155 case kMathAbs: |
| 1373 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1156 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1374 case kMathFloor: | 1157 case kMathFloor: |
| 1375 return AssignEnvironment(DefineAsRegister(result)); | 1158 return AssignEnvironment(DefineAsRegister(result)); |
| 1376 case kMathRound: | 1159 case kMathRound: |
| 1377 return AssignEnvironment(DefineAsRegister(result)); | 1160 return AssignEnvironment(DefineAsRegister(result)); |
| 1378 case kMathSqrt: | 1161 case kMathSqrt: |
| 1379 return DefineSameAsFirst(result); | 1162 return DefineSameAsFirst(result); |
| 1380 case kMathPowHalf: | 1163 case kMathPowHalf: |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1409 | 1192 |
| 1410 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { | 1193 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { |
| 1411 argument_count_ -= instr->argument_count(); | 1194 argument_count_ -= instr->argument_count(); |
| 1412 return MarkAsCall(DefineFixed(new LCallKnownGlobal, eax), instr); | 1195 return MarkAsCall(DefineFixed(new LCallKnownGlobal, eax), instr); |
| 1413 } | 1196 } |
| 1414 | 1197 |
| 1415 | 1198 |
| 1416 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { | 1199 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { |
| 1417 LOperand* constructor = UseFixed(instr->constructor(), edi); | 1200 LOperand* constructor = UseFixed(instr->constructor(), edi); |
| 1418 argument_count_ -= instr->argument_count(); | 1201 argument_count_ -= instr->argument_count(); |
| 1419 LInstruction* result = new LCallNew(constructor); | 1202 LCallNew* result = new LCallNew(constructor); |
| 1420 return MarkAsCall(DefineFixed(result, eax), instr); | 1203 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1421 } | 1204 } |
| 1422 | 1205 |
| 1423 | 1206 |
| 1424 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { | 1207 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
| 1425 argument_count_ -= instr->argument_count(); | 1208 argument_count_ -= instr->argument_count(); |
| 1426 return MarkAsCall(DefineFixed(new LCallFunction, eax), instr); | 1209 return MarkAsCall(DefineFixed(new LCallFunction, eax), instr); |
| 1427 } | 1210 } |
| 1428 | 1211 |
| 1429 | 1212 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1449 | 1232 |
| 1450 | 1233 |
| 1451 LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) { | 1234 LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) { |
| 1452 return DoBit(Token::BIT_AND, instr); | 1235 return DoBit(Token::BIT_AND, instr); |
| 1453 } | 1236 } |
| 1454 | 1237 |
| 1455 | 1238 |
| 1456 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { | 1239 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { |
| 1457 ASSERT(instr->value()->representation().IsInteger32()); | 1240 ASSERT(instr->value()->representation().IsInteger32()); |
| 1458 ASSERT(instr->representation().IsInteger32()); | 1241 ASSERT(instr->representation().IsInteger32()); |
| 1459 return DefineSameAsFirst(new LBitNotI(UseRegisterAtStart(instr->value()))); | 1242 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1243 LBitNotI* result = new LBitNotI(input); |
| 1244 return DefineSameAsFirst(result); |
| 1460 } | 1245 } |
| 1461 | 1246 |
| 1462 | 1247 |
| 1463 LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) { | 1248 LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) { |
| 1464 return DoBit(Token::BIT_OR, instr); | 1249 return DoBit(Token::BIT_OR, instr); |
| 1465 } | 1250 } |
| 1466 | 1251 |
| 1467 | 1252 |
| 1468 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { | 1253 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { |
| 1469 return DoBit(Token::BIT_XOR, instr); | 1254 return DoBit(Token::BIT_XOR, instr); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1489 | 1274 |
| 1490 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1275 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1491 if (instr->representation().IsInteger32()) { | 1276 if (instr->representation().IsInteger32()) { |
| 1492 ASSERT(instr->left()->representation().IsInteger32()); | 1277 ASSERT(instr->left()->representation().IsInteger32()); |
| 1493 ASSERT(instr->right()->representation().IsInteger32()); | 1278 ASSERT(instr->right()->representation().IsInteger32()); |
| 1494 // The temporary operand is necessary to ensure that right is not allocated | 1279 // The temporary operand is necessary to ensure that right is not allocated |
| 1495 // into edx. | 1280 // into edx. |
| 1496 FixedTemp(edx); | 1281 FixedTemp(edx); |
| 1497 LOperand* value = UseFixed(instr->left(), eax); | 1282 LOperand* value = UseFixed(instr->left(), eax); |
| 1498 LOperand* divisor = UseRegister(instr->right()); | 1283 LOperand* divisor = UseRegister(instr->right()); |
| 1499 LInstruction* result = DefineFixed(new LModI(value, divisor), edx); | 1284 LModI* mod = new LModI(value, divisor); |
| 1500 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) || | 1285 LInstruction* result = DefineFixed(mod, edx); |
| 1501 instr->CheckFlag(HValue::kCanBeDivByZero)) { | 1286 return (instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1502 result = AssignEnvironment(result); | 1287 instr->CheckFlag(HValue::kCanBeDivByZero)) |
| 1503 } | 1288 ? AssignEnvironment(result) |
| 1504 return result; | 1289 : result; |
| 1505 } else if (instr->representation().IsTagged()) { | 1290 } else if (instr->representation().IsTagged()) { |
| 1506 return DoArithmeticT(Token::MOD, instr); | 1291 return DoArithmeticT(Token::MOD, instr); |
| 1507 } else { | 1292 } else { |
| 1508 ASSERT(instr->representation().IsDouble()); | 1293 ASSERT(instr->representation().IsDouble()); |
| 1509 // We call a C function for double modulo. It can't trigger a GC. | 1294 // We call a C function for double modulo. It can't trigger a GC. |
| 1510 // We need to use fixed result register for the call. | 1295 // We need to use fixed result register for the call. |
| 1511 // TODO(fschneider): Allow any register as input registers. | 1296 // TODO(fschneider): Allow any register as input registers. |
| 1512 LOperand* left = UseFixedDouble(instr->left(), xmm1); | 1297 LOperand* left = UseFixedDouble(instr->left(), xmm1); |
| 1513 LOperand* right = UseFixedDouble(instr->right(), xmm2); | 1298 LOperand* right = UseFixedDouble(instr->right(), xmm2); |
| 1514 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right); | 1299 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1591 UseFixedDouble(instr->right(), xmm2) : | 1376 UseFixedDouble(instr->right(), xmm2) : |
| 1592 UseFixed(instr->right(), eax); | 1377 UseFixed(instr->right(), eax); |
| 1593 LPower* result = new LPower(left, right); | 1378 LPower* result = new LPower(left, right); |
| 1594 return MarkAsCall(DefineFixedDouble(result, xmm3), instr, | 1379 return MarkAsCall(DefineFixedDouble(result, xmm3), instr, |
| 1595 CAN_DEOPTIMIZE_EAGERLY); | 1380 CAN_DEOPTIMIZE_EAGERLY); |
| 1596 } | 1381 } |
| 1597 | 1382 |
| 1598 | 1383 |
| 1599 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { | 1384 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { |
| 1600 Token::Value op = instr->token(); | 1385 Token::Value op = instr->token(); |
| 1601 if (instr->left()->representation().IsInteger32()) { | 1386 Representation r = instr->GetInputRepresentation(); |
| 1387 if (r.IsInteger32()) { |
| 1388 ASSERT(instr->left()->representation().IsInteger32()); |
| 1602 ASSERT(instr->right()->representation().IsInteger32()); | 1389 ASSERT(instr->right()->representation().IsInteger32()); |
| 1603 LOperand* left = UseRegisterAtStart(instr->left()); | 1390 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1604 LOperand* right = UseOrConstantAtStart(instr->right()); | 1391 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1605 return DefineAsRegister(new LCmpID(op, left, right, false)); | 1392 return DefineAsRegister(new LCmpID(left, right)); |
| 1606 } else if (instr->left()->representation().IsDouble()) { | 1393 } else if (r.IsDouble()) { |
| 1394 ASSERT(instr->left()->representation().IsDouble()); |
| 1607 ASSERT(instr->right()->representation().IsDouble()); | 1395 ASSERT(instr->right()->representation().IsDouble()); |
| 1608 LOperand* left = UseRegisterAtStart(instr->left()); | 1396 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1609 LOperand* right = UseRegisterAtStart(instr->right()); | 1397 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1610 return DefineAsRegister(new LCmpID(op, left, right, true)); | 1398 return DefineAsRegister(new LCmpID(left, right)); |
| 1611 } else { | 1399 } else { |
| 1400 ASSERT(instr->left()->representation().IsTagged()); |
| 1401 ASSERT(instr->right()->representation().IsTagged()); |
| 1612 bool reversed = (op == Token::GT || op == Token::LTE); | 1402 bool reversed = (op == Token::GT || op == Token::LTE); |
| 1613 LOperand* left = UseFixed(instr->left(), reversed ? eax : edx); | 1403 LOperand* left = UseFixed(instr->left(), reversed ? eax : edx); |
| 1614 LOperand* right = UseFixed(instr->right(), reversed ? edx : eax); | 1404 LOperand* right = UseFixed(instr->right(), reversed ? edx : eax); |
| 1615 LInstruction* result = new LCmpT(left, right); | 1405 LCmpT* result = new LCmpT(left, right); |
| 1616 return MarkAsCall(DefineFixed(result, eax), instr); | 1406 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1617 } | 1407 } |
| 1618 } | 1408 } |
| 1619 | 1409 |
| 1620 | 1410 |
| 1621 LInstruction* LChunkBuilder::DoCompareJSObjectEq( | 1411 LInstruction* LChunkBuilder::DoCompareJSObjectEq( |
| 1622 HCompareJSObjectEq* instr) { | 1412 HCompareJSObjectEq* instr) { |
| 1623 LOperand* left = UseRegisterAtStart(instr->left()); | 1413 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1624 LOperand* right = UseRegisterAtStart(instr->right()); | 1414 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1625 LInstruction* result = new LCmpJSObjectEq(left, right); | 1415 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right); |
| 1626 return DefineAsRegister(result); | 1416 return DefineAsRegister(result); |
| 1627 } | 1417 } |
| 1628 | 1418 |
| 1629 | 1419 |
| 1630 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) { | 1420 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) { |
| 1631 ASSERT(instr->value()->representation().IsTagged()); | 1421 ASSERT(instr->value()->representation().IsTagged()); |
| 1632 LOperand* value = UseRegisterAtStart(instr->value()); | 1422 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1633 | 1423 |
| 1634 return DefineAsRegister(new LIsNull(value, | 1424 return DefineAsRegister(new LIsNull(value)); |
| 1635 instr->is_strict())); | |
| 1636 } | 1425 } |
| 1637 | 1426 |
| 1638 | 1427 |
| 1639 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) { | 1428 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) { |
| 1640 ASSERT(instr->value()->representation().IsTagged()); | 1429 ASSERT(instr->value()->representation().IsTagged()); |
| 1641 LOperand* value = UseRegister(instr->value()); | 1430 LOperand* value = UseRegister(instr->value()); |
| 1642 | 1431 |
| 1643 return DefineAsRegister(new LIsObject(value, TempRegister())); | 1432 return DefineAsRegister(new LIsObject(value, TempRegister())); |
| 1644 } | 1433 } |
| 1645 | 1434 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1670 | 1459 |
| 1671 | 1460 |
| 1672 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { | 1461 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { |
| 1673 ASSERT(instr->value()->representation().IsTagged()); | 1462 ASSERT(instr->value()->representation().IsTagged()); |
| 1674 LOperand* value = UseTempRegister(instr->value()); | 1463 LOperand* value = UseTempRegister(instr->value()); |
| 1675 | 1464 |
| 1676 return DefineSameAsFirst(new LClassOfTest(value, TempRegister())); | 1465 return DefineSameAsFirst(new LClassOfTest(value, TempRegister())); |
| 1677 } | 1466 } |
| 1678 | 1467 |
| 1679 | 1468 |
| 1680 LInstruction* LChunkBuilder::DoArrayLength(HArrayLength* instr) { | 1469 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { |
| 1681 LOperand* array = NULL; | 1470 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1682 LOperand* temporary = NULL; | 1471 return DefineAsRegister(new LJSArrayLength(array)); |
| 1472 } |
| 1683 | 1473 |
| 1684 if (instr->value()->IsLoadElements()) { | |
| 1685 array = UseRegisterAtStart(instr->value()); | |
| 1686 } else { | |
| 1687 array = UseRegister(instr->value()); | |
| 1688 temporary = TempRegister(); | |
| 1689 } | |
| 1690 | 1474 |
| 1691 LInstruction* result = new LArrayLength(array, temporary); | 1475 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { |
| 1692 return AssignEnvironment(DefineAsRegister(result)); | 1476 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1477 return DefineAsRegister(new LFixedArrayLength(array)); |
| 1693 } | 1478 } |
| 1694 | 1479 |
| 1695 | 1480 |
| 1696 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | 1481 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { |
| 1697 LOperand* object = UseRegister(instr->value()); | 1482 LOperand* object = UseRegister(instr->value()); |
| 1698 LInstruction* result = new LValueOf(object, TempRegister()); | 1483 LValueOf* result = new LValueOf(object, TempRegister()); |
| 1699 return AssignEnvironment(DefineSameAsFirst(result)); | 1484 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1700 } | 1485 } |
| 1701 | 1486 |
| 1702 | 1487 |
| 1703 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1488 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
| 1704 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), | 1489 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), |
| 1705 Use(instr->length()))); | 1490 Use(instr->length()))); |
| 1706 } | 1491 } |
| 1707 | 1492 |
| 1708 | 1493 |
| 1709 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { | 1494 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
| 1710 LOperand* value = UseFixed(instr->value(), eax); | 1495 LOperand* value = UseFixed(instr->value(), eax); |
| 1711 return MarkAsCall(new LThrow(value), instr); | 1496 return MarkAsCall(new LThrow(value), instr); |
| 1712 } | 1497 } |
| 1713 | 1498 |
| 1714 | 1499 |
| 1715 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1500 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
| 1716 Representation from = instr->from(); | 1501 Representation from = instr->from(); |
| 1717 Representation to = instr->to(); | 1502 Representation to = instr->to(); |
| 1718 if (from.IsTagged()) { | 1503 if (from.IsTagged()) { |
| 1719 if (to.IsDouble()) { | 1504 if (to.IsDouble()) { |
| 1720 LOperand* value = UseRegister(instr->value()); | 1505 LOperand* value = UseRegister(instr->value()); |
| 1721 LInstruction* res = new LNumberUntagD(value); | 1506 LNumberUntagD* res = new LNumberUntagD(value); |
| 1722 return AssignEnvironment(DefineAsRegister(res)); | 1507 return AssignEnvironment(DefineAsRegister(res)); |
| 1723 } else { | 1508 } else { |
| 1724 ASSERT(to.IsInteger32()); | 1509 ASSERT(to.IsInteger32()); |
| 1725 LOperand* value = UseRegister(instr->value()); | 1510 LOperand* value = UseRegister(instr->value()); |
| 1726 bool needs_check = !instr->value()->type().IsSmi(); | 1511 bool needs_check = !instr->value()->type().IsSmi(); |
| 1727 if (needs_check) { | 1512 if (needs_check) { |
| 1728 CpuFeatures* cpu_features = Isolate::Current()->cpu_features(); | 1513 CpuFeatures* cpu_features = Isolate::Current()->cpu_features(); |
| 1729 LOperand* xmm_temp = | 1514 LOperand* xmm_temp = |
| 1730 (instr->CanTruncateToInt32() && !cpu_features->IsSupported(SSE3)) | 1515 (instr->CanTruncateToInt32() && !cpu_features->IsSupported(SSE3)) |
| 1731 ? NULL | 1516 ? NULL |
| 1732 : FixedTemp(xmm1); | 1517 : FixedTemp(xmm1); |
| 1733 LInstruction* res = new LTaggedToI(value, xmm_temp); | 1518 LTaggedToI* res = new LTaggedToI(value, xmm_temp); |
| 1734 return AssignEnvironment(DefineSameAsFirst(res)); | 1519 return AssignEnvironment(DefineSameAsFirst(res)); |
| 1735 } else { | 1520 } else { |
| 1736 return DefineSameAsFirst(new LSmiUntag(value, needs_check)); | 1521 return DefineSameAsFirst(new LSmiUntag(value, needs_check)); |
| 1737 } | 1522 } |
| 1738 } | 1523 } |
| 1739 } else if (from.IsDouble()) { | 1524 } else if (from.IsDouble()) { |
| 1740 if (to.IsTagged()) { | 1525 if (to.IsTagged()) { |
| 1741 LOperand* value = UseRegister(instr->value()); | 1526 LOperand* value = UseRegister(instr->value()); |
| 1742 LOperand* temp = TempRegister(); | 1527 LOperand* temp = TempRegister(); |
| 1743 | 1528 |
| 1744 // Make sure that temp and result_temp are different registers. | 1529 // Make sure that temp and result_temp are different registers. |
| 1745 LUnallocated* result_temp = TempRegister(); | 1530 LUnallocated* result_temp = TempRegister(); |
| 1746 LInstruction* result = new LNumberTagD(value, temp); | 1531 LNumberTagD* result = new LNumberTagD(value, temp); |
| 1747 return AssignPointerMap(Define(result, result_temp)); | 1532 return AssignPointerMap(Define(result, result_temp)); |
| 1748 } else { | 1533 } else { |
| 1749 ASSERT(to.IsInteger32()); | 1534 ASSERT(to.IsInteger32()); |
| 1750 LOperand* value = UseRegister(instr->value()); | 1535 bool needs_temp = instr->CanTruncateToInt32() && |
| 1751 return AssignEnvironment(DefineAsRegister(new LDoubleToI(value))); | 1536 !Isolate::Current()->cpu_features()->IsSupported(SSE3); |
| 1537 LOperand* value = needs_temp ? |
| 1538 UseTempRegister(instr->value()) : UseRegister(instr->value()); |
| 1539 LOperand* temp = needs_temp ? TempRegister() : NULL; |
| 1540 return AssignEnvironment(DefineAsRegister(new LDoubleToI(value, temp))); |
| 1752 } | 1541 } |
| 1753 } else if (from.IsInteger32()) { | 1542 } else if (from.IsInteger32()) { |
| 1754 if (to.IsTagged()) { | 1543 if (to.IsTagged()) { |
| 1755 HValue* val = instr->value(); | 1544 HValue* val = instr->value(); |
| 1756 LOperand* value = UseRegister(val); | 1545 LOperand* value = UseRegister(val); |
| 1757 if (val->HasRange() && val->range()->IsInSmiRange()) { | 1546 if (val->HasRange() && val->range()->IsInSmiRange()) { |
| 1758 return DefineSameAsFirst(new LSmiTag(value)); | 1547 return DefineSameAsFirst(new LSmiTag(value)); |
| 1759 } else { | 1548 } else { |
| 1760 LInstruction* result = new LNumberTagI(value); | 1549 LNumberTagI* result = new LNumberTagI(value); |
| 1761 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1550 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1762 } | 1551 } |
| 1763 } else { | 1552 } else { |
| 1764 ASSERT(to.IsDouble()); | 1553 ASSERT(to.IsDouble()); |
| 1765 return DefineAsRegister(new LInteger32ToDouble(Use(instr->value()))); | 1554 return DefineAsRegister(new LInteger32ToDouble(Use(instr->value()))); |
| 1766 } | 1555 } |
| 1767 } | 1556 } |
| 1768 UNREACHABLE(); | 1557 UNREACHABLE(); |
| 1769 return NULL; | 1558 return NULL; |
| 1770 } | 1559 } |
| 1771 | 1560 |
| 1772 | 1561 |
| 1773 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { | 1562 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { |
| 1774 LOperand* value = UseRegisterAtStart(instr->value()); | 1563 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1775 return AssignEnvironment(new LCheckSmi(value, zero)); | 1564 return AssignEnvironment(new LCheckSmi(value, zero)); |
| 1776 } | 1565 } |
| 1777 | 1566 |
| 1778 | 1567 |
| 1779 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 1568 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
| 1780 LOperand* value = UseRegisterAtStart(instr->value()); | 1569 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1781 LOperand* temp = TempRegister(); | 1570 LOperand* temp = TempRegister(); |
| 1782 LInstruction* result = new LCheckInstanceType(value, temp); | 1571 LCheckInstanceType* result = new LCheckInstanceType(value, temp); |
| 1783 return AssignEnvironment(result); | 1572 return AssignEnvironment(result); |
| 1784 } | 1573 } |
| 1785 | 1574 |
| 1786 | 1575 |
| 1787 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { | 1576 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { |
| 1788 LOperand* temp = TempRegister(); | 1577 LOperand* temp = TempRegister(); |
| 1789 LInstruction* result = | 1578 LCheckPrototypeMaps* result = new LCheckPrototypeMaps(temp); |
| 1790 new LCheckPrototypeMaps(temp, | |
| 1791 instr->holder(), | |
| 1792 instr->receiver_map()); | |
| 1793 return AssignEnvironment(result); | 1579 return AssignEnvironment(result); |
| 1794 } | 1580 } |
| 1795 | 1581 |
| 1796 | 1582 |
| 1797 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { | 1583 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { |
| 1798 LOperand* value = UseRegisterAtStart(instr->value()); | 1584 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1799 return AssignEnvironment(new LCheckSmi(value, not_zero)); | 1585 return AssignEnvironment(new LCheckSmi(value, not_zero)); |
| 1800 } | 1586 } |
| 1801 | 1587 |
| 1802 | 1588 |
| 1803 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { | 1589 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { |
| 1804 LOperand* value = UseRegisterAtStart(instr->value()); | 1590 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1805 return AssignEnvironment(new LCheckFunction(value)); | 1591 return AssignEnvironment(new LCheckFunction(value)); |
| 1806 } | 1592 } |
| 1807 | 1593 |
| 1808 | 1594 |
| 1809 LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) { | 1595 LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) { |
| 1810 LOperand* value = UseRegisterAtStart(instr->value()); | 1596 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1811 LInstruction* result = new LCheckMap(value); | 1597 LCheckMap* result = new LCheckMap(value); |
| 1812 return AssignEnvironment(result); | 1598 return AssignEnvironment(result); |
| 1813 } | 1599 } |
| 1814 | 1600 |
| 1815 | 1601 |
| 1816 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 1602 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
| 1817 return new LReturn(UseFixed(instr->value(), eax)); | 1603 return new LReturn(UseFixed(instr->value(), eax)); |
| 1818 } | 1604 } |
| 1819 | 1605 |
| 1820 | 1606 |
| 1821 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { | 1607 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
| 1822 Representation r = instr->representation(); | 1608 Representation r = instr->representation(); |
| 1823 if (r.IsInteger32()) { | 1609 if (r.IsInteger32()) { |
| 1824 int32_t value = instr->Integer32Value(); | 1610 int32_t value = instr->Integer32Value(); |
| 1825 return DefineAsRegister(new LConstantI(value)); | 1611 return DefineAsRegister(new LConstantI(value)); |
| 1826 } else if (r.IsDouble()) { | 1612 } else if (r.IsDouble()) { |
| 1827 double value = instr->DoubleValue(); | 1613 double value = instr->DoubleValue(); |
| 1828 return DefineAsRegister(new LConstantD(value)); | 1614 return DefineAsRegister(new LConstantD(value)); |
| 1829 } else if (r.IsTagged()) { | 1615 } else if (r.IsTagged()) { |
| 1830 return DefineAsRegister(new LConstantT(instr->handle())); | 1616 return DefineAsRegister(new LConstantT(instr->handle())); |
| 1831 } else { | 1617 } else { |
| 1832 Abort("unsupported constant of type double"); | 1618 Abort("unsupported constant of type double"); |
| 1833 return NULL; | 1619 return NULL; |
| 1834 } | 1620 } |
| 1835 } | 1621 } |
| 1836 | 1622 |
| 1837 | 1623 |
| 1838 LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) { | 1624 LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) { |
| 1839 LInstruction* result = new LLoadGlobal; | 1625 LLoadGlobal* result = new LLoadGlobal; |
| 1840 return instr->check_hole_value() | 1626 return instr->check_hole_value() |
| 1841 ? AssignEnvironment(DefineAsRegister(result)) | 1627 ? AssignEnvironment(DefineAsRegister(result)) |
| 1842 : DefineAsRegister(result); | 1628 : DefineAsRegister(result); |
| 1843 } | 1629 } |
| 1844 | 1630 |
| 1845 | 1631 |
| 1846 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) { | 1632 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) { |
| 1847 return new LStoreGlobal(UseRegisterAtStart(instr->value())); | 1633 return new LStoreGlobal(UseRegisterAtStart(instr->value())); |
| 1848 } | 1634 } |
| 1849 | 1635 |
| 1850 | 1636 |
| 1851 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 1637 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
| 1852 return DefineAsRegister( | 1638 ASSERT(instr->representation().IsTagged()); |
| 1853 new LLoadNamedField(UseRegisterAtStart(instr->object()))); | 1639 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1640 return DefineAsRegister(new LLoadNamedField(obj)); |
| 1854 } | 1641 } |
| 1855 | 1642 |
| 1856 | 1643 |
| 1857 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { | 1644 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
| 1858 LOperand* object = UseFixed(instr->object(), eax); | 1645 LOperand* object = UseFixed(instr->object(), eax); |
| 1859 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), eax); | 1646 LLoadNamedGeneric* result = new LLoadNamedGeneric(object); |
| 1860 return MarkAsCall(result, instr); | 1647 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1648 } |
| 1649 |
| 1650 |
| 1651 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( |
| 1652 HLoadFunctionPrototype* instr) { |
| 1653 return AssignEnvironment(DefineAsRegister( |
| 1654 new LLoadFunctionPrototype(UseRegister(instr->function()), |
| 1655 TempRegister()))); |
| 1861 } | 1656 } |
| 1862 | 1657 |
| 1863 | 1658 |
| 1864 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { | 1659 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { |
| 1865 LOperand* input = UseRegisterAtStart(instr->value()); | 1660 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1866 return DefineSameAsFirst(new LLoadElements(input)); | 1661 return DefineSameAsFirst(new LLoadElements(input)); |
| 1867 } | 1662 } |
| 1868 | 1663 |
| 1869 | 1664 |
| 1870 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( | 1665 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( |
| 1871 HLoadKeyedFastElement* instr) { | 1666 HLoadKeyedFastElement* instr) { |
| 1872 Representation r = instr->representation(); | 1667 ASSERT(instr->representation().IsTagged()); |
| 1668 ASSERT(instr->key()->representation().IsInteger32()); |
| 1873 LOperand* obj = UseRegisterAtStart(instr->object()); | 1669 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1874 ASSERT(instr->key()->representation().IsInteger32()); | |
| 1875 LOperand* key = UseRegisterAtStart(instr->key()); | 1670 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1876 LOperand* load_result = NULL; | 1671 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); |
| 1877 // Double needs an extra temp, because the result is converted from heap | 1672 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1878 // number to a double register. | |
| 1879 if (r.IsDouble()) load_result = TempRegister(); | |
| 1880 LInstruction* result = new LLoadKeyedFastElement(obj, | |
| 1881 key, | |
| 1882 load_result); | |
| 1883 if (r.IsDouble()) { | |
| 1884 result = DefineAsRegister(result); | |
| 1885 } else { | |
| 1886 result = DefineSameAsFirst(result); | |
| 1887 } | |
| 1888 return AssignEnvironment(result); | |
| 1889 } | 1673 } |
| 1890 | 1674 |
| 1891 | 1675 |
| 1892 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1676 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 1893 LOperand* object = UseFixed(instr->object(), edx); | 1677 LOperand* object = UseFixed(instr->object(), edx); |
| 1894 LOperand* key = UseFixed(instr->key(), eax); | 1678 LOperand* key = UseFixed(instr->key(), eax); |
| 1895 | 1679 |
| 1896 LInstruction* result = | 1680 LLoadKeyedGeneric* result = new LLoadKeyedGeneric(object, key); |
| 1897 DefineFixed(new LLoadKeyedGeneric(object, key), eax); | 1681 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1898 return MarkAsCall(result, instr); | |
| 1899 } | 1682 } |
| 1900 | 1683 |
| 1901 | 1684 |
| 1902 LInstruction* LChunkBuilder::DoStoreKeyedFastElement( | 1685 LInstruction* LChunkBuilder::DoStoreKeyedFastElement( |
| 1903 HStoreKeyedFastElement* instr) { | 1686 HStoreKeyedFastElement* instr) { |
| 1904 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 1687 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 1905 ASSERT(instr->value()->representation().IsTagged()); | 1688 ASSERT(instr->value()->representation().IsTagged()); |
| 1906 ASSERT(instr->object()->representation().IsTagged()); | 1689 ASSERT(instr->object()->representation().IsTagged()); |
| 1907 ASSERT(instr->key()->representation().IsInteger32()); | 1690 ASSERT(instr->key()->representation().IsInteger32()); |
| 1908 | 1691 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1925 | 1708 |
| 1926 ASSERT(instr->object()->representation().IsTagged()); | 1709 ASSERT(instr->object()->representation().IsTagged()); |
| 1927 ASSERT(instr->key()->representation().IsTagged()); | 1710 ASSERT(instr->key()->representation().IsTagged()); |
| 1928 ASSERT(instr->value()->representation().IsTagged()); | 1711 ASSERT(instr->value()->representation().IsTagged()); |
| 1929 | 1712 |
| 1930 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); | 1713 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); |
| 1931 } | 1714 } |
| 1932 | 1715 |
| 1933 | 1716 |
| 1934 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { | 1717 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { |
| 1935 bool needs_write_barrier = !instr->value()->type().IsSmi(); | 1718 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 1936 | 1719 |
| 1937 LOperand* obj = needs_write_barrier | 1720 LOperand* obj = needs_write_barrier |
| 1938 ? UseTempRegister(instr->object()) | 1721 ? UseTempRegister(instr->object()) |
| 1939 : UseRegisterAtStart(instr->object()); | 1722 : UseRegisterAtStart(instr->object()); |
| 1940 | 1723 |
| 1941 LOperand* val = needs_write_barrier | 1724 LOperand* val = needs_write_barrier |
| 1942 ? UseTempRegister(instr->value()) | 1725 ? UseTempRegister(instr->value()) |
| 1943 : UseRegister(instr->value()); | 1726 : UseRegister(instr->value()); |
| 1944 | 1727 |
| 1945 // We only need a scratch register if we have a write barrier or we | 1728 // We only need a scratch register if we have a write barrier or we |
| 1946 // have a store into the properties array (not in-object-property). | 1729 // have a store into the properties array (not in-object-property). |
| 1947 LOperand* temp = (!instr->is_in_object() || needs_write_barrier) | 1730 LOperand* temp = (!instr->is_in_object() || needs_write_barrier) |
| 1948 ? TempRegister() : NULL; | 1731 ? TempRegister() : NULL; |
| 1949 | 1732 |
| 1950 return new LStoreNamedField(obj, | 1733 return new LStoreNamedField(obj, val, temp); |
| 1951 instr->name(), | |
| 1952 val, | |
| 1953 instr->is_in_object(), | |
| 1954 instr->offset(), | |
| 1955 temp, | |
| 1956 needs_write_barrier, | |
| 1957 instr->transition()); | |
| 1958 } | 1734 } |
| 1959 | 1735 |
| 1960 | 1736 |
| 1961 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 1737 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
| 1962 LOperand* obj = UseFixed(instr->object(), edx); | 1738 LOperand* obj = UseFixed(instr->object(), edx); |
| 1963 LOperand* val = UseFixed(instr->value(), eax); | 1739 LOperand* val = UseFixed(instr->value(), eax); |
| 1964 | 1740 |
| 1965 LInstruction* result = new LStoreNamedGeneric(obj, instr->name(), val); | 1741 LStoreNamedGeneric* result = new LStoreNamedGeneric(obj, val); |
| 1966 return MarkAsCall(result, instr); | 1742 return MarkAsCall(result, instr); |
| 1967 } | 1743 } |
| 1968 | 1744 |
| 1969 | 1745 |
| 1970 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { | 1746 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { |
| 1971 return MarkAsCall(DefineFixed(new LArrayLiteral, eax), instr); | 1747 return MarkAsCall(DefineFixed(new LArrayLiteral, eax), instr); |
| 1972 } | 1748 } |
| 1973 | 1749 |
| 1974 | 1750 |
| 1975 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { | 1751 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { |
| 1976 return MarkAsCall(DefineFixed(new LObjectLiteral, eax), instr); | 1752 return MarkAsCall(DefineFixed(new LObjectLiteral, eax), instr); |
| 1977 } | 1753 } |
| 1978 | 1754 |
| 1979 | 1755 |
| 1980 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { | 1756 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { |
| 1981 return MarkAsCall(DefineFixed(new LRegExpLiteral, eax), instr); | 1757 return MarkAsCall(DefineFixed(new LRegExpLiteral, eax), instr); |
| 1982 } | 1758 } |
| 1983 | 1759 |
| 1984 | 1760 |
| 1985 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { | 1761 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { |
| 1986 return MarkAsCall(DefineFixed(new LFunctionLiteral, eax), instr); | 1762 return MarkAsCall(DefineFixed(new LFunctionLiteral, eax), instr); |
| 1987 } | 1763 } |
| 1988 | 1764 |
| 1989 | 1765 |
| 1990 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { | 1766 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { |
| 1991 LInstruction* result = new LDeleteProperty(Use(instr->object()), | 1767 LDeleteProperty* result = new LDeleteProperty(Use(instr->object()), |
| 1992 UseOrConstant(instr->key())); | 1768 UseOrConstant(instr->key())); |
| 1993 return MarkAsCall(DefineFixed(result, eax), instr); | 1769 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1994 } | 1770 } |
| 1995 | 1771 |
| 1996 | 1772 |
| 1997 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { | 1773 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { |
| 1998 allocator_->MarkAsOsrEntry(); | 1774 allocator_->MarkAsOsrEntry(); |
| 1999 current_block_->last_environment()->set_ast_id(instr->ast_id()); | 1775 current_block_->last_environment()->set_ast_id(instr->ast_id()); |
| 2000 return AssignEnvironment(new LOsrEntry); | 1776 return AssignEnvironment(new LOsrEntry); |
| 2001 } | 1777 } |
| 2002 | 1778 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2023 // There are no real uses of the arguments object (we bail out in all other | 1799 // There are no real uses of the arguments object (we bail out in all other |
| 2024 // cases). | 1800 // cases). |
| 2025 return NULL; | 1801 return NULL; |
| 2026 } | 1802 } |
| 2027 | 1803 |
| 2028 | 1804 |
| 2029 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { | 1805 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { |
| 2030 LOperand* arguments = UseRegister(instr->arguments()); | 1806 LOperand* arguments = UseRegister(instr->arguments()); |
| 2031 LOperand* length = UseTempRegister(instr->length()); | 1807 LOperand* length = UseTempRegister(instr->length()); |
| 2032 LOperand* index = Use(instr->index()); | 1808 LOperand* index = Use(instr->index()); |
| 2033 LInstruction* result = new LAccessArgumentsAt(arguments, length, index); | 1809 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index); |
| 2034 return DefineAsRegister(AssignEnvironment(result)); | 1810 return AssignEnvironment(DefineAsRegister(result)); |
| 2035 } | 1811 } |
| 2036 | 1812 |
| 2037 | 1813 |
| 2038 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 1814 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
| 2039 LInstruction* result = new LTypeof(Use(instr->value())); | 1815 LTypeof* result = new LTypeof(UseAtStart(instr->value())); |
| 2040 return MarkAsCall(DefineFixed(result, eax), instr); | 1816 return MarkAsCall(DefineFixed(result, eax), instr); |
| 2041 } | 1817 } |
| 2042 | 1818 |
| 2043 | 1819 |
| 2044 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { | 1820 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { |
| 2045 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); | 1821 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); |
| 2046 } | 1822 } |
| 2047 | 1823 |
| 2048 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 1824 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 2049 HEnvironment* env = current_block_->last_environment(); | 1825 HEnvironment* env = current_block_->last_environment(); |
| 2050 ASSERT(env != NULL); | 1826 ASSERT(env != NULL); |
| 2051 | 1827 |
| 2052 env->set_ast_id(instr->ast_id()); | 1828 env->set_ast_id(instr->ast_id()); |
| 2053 | 1829 |
| 2054 env->Drop(instr->pop_count()); | 1830 env->Drop(instr->pop_count()); |
| 2055 for (int i = 0; i < instr->values()->length(); ++i) { | 1831 for (int i = 0; i < instr->values()->length(); ++i) { |
| 2056 HValue* value = instr->values()->at(i); | 1832 HValue* value = instr->values()->at(i); |
| 2057 if (instr->HasAssignedIndexAt(i)) { | 1833 if (instr->HasAssignedIndexAt(i)) { |
| 2058 env->Bind(instr->GetAssignedIndexAt(i), value); | 1834 env->Bind(instr->GetAssignedIndexAt(i), value); |
| 2059 } else { | 1835 } else { |
| 2060 env->Push(value); | 1836 env->Push(value); |
| 2061 } | 1837 } |
| 2062 } | 1838 } |
| 2063 | 1839 ASSERT(env->length() == instr->environment_length()); |
| 2064 if (FLAG_trace_environment) { | |
| 2065 PrintF("Reconstructed environment ast_id=%d, instr_id=%d\n", | |
| 2066 instr->ast_id(), | |
| 2067 instr->id()); | |
| 2068 env->PrintToStd(); | |
| 2069 } | |
| 2070 ASSERT(env->values()->length() == instr->environment_height()); | |
| 2071 | 1840 |
| 2072 // If there is an instruction pending deoptimization environment create a | 1841 // If there is an instruction pending deoptimization environment create a |
| 2073 // lazy bailout instruction to capture the environment. | 1842 // lazy bailout instruction to capture the environment. |
| 2074 if (pending_deoptimization_ast_id_ == instr->ast_id()) { | 1843 if (pending_deoptimization_ast_id_ == instr->ast_id()) { |
| 2075 LInstruction* result = new LLazyBailout; | 1844 LLazyBailout* lazy_bailout = new LLazyBailout; |
| 2076 result = AssignEnvironment(result); | 1845 LInstruction* result = AssignEnvironment(lazy_bailout); |
| 2077 instructions_pending_deoptimization_environment_-> | 1846 instructions_pending_deoptimization_environment_-> |
| 2078 set_deoptimization_environment(result->environment()); | 1847 set_deoptimization_environment(result->environment()); |
| 2079 ClearInstructionPendingDeoptimizationEnvironment(); | 1848 ClearInstructionPendingDeoptimizationEnvironment(); |
| 2080 return result; | 1849 return result; |
| 2081 } | 1850 } |
| 2082 | 1851 |
| 2083 return NULL; | 1852 return NULL; |
| 2084 } | 1853 } |
| 2085 | 1854 |
| 2086 | 1855 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2102 } | 1871 } |
| 2103 | 1872 |
| 2104 | 1873 |
| 2105 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 1874 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 2106 HEnvironment* outer = current_block_->last_environment()->outer(); | 1875 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 2107 current_block_->UpdateEnvironment(outer); | 1876 current_block_->UpdateEnvironment(outer); |
| 2108 return NULL; | 1877 return NULL; |
| 2109 } | 1878 } |
| 2110 | 1879 |
| 2111 | 1880 |
| 2112 void LPointerMap::RecordPointer(LOperand* op) { | 1881 } } // namespace v8::internal |
| 2113 // Do not record arguments as pointers. | |
| 2114 if (op->IsStackSlot() && op->index() < 0) return; | |
| 2115 ASSERT(!op->IsDoubleRegister() && !op->IsDoubleStackSlot()); | |
| 2116 pointer_operands_.Add(op); | |
| 2117 } | |
| 2118 | 1882 |
| 2119 | 1883 #endif // V8_TARGET_ARCH_IA32 |
| 2120 void LPointerMap::PrintTo(StringStream* stream) const { | |
| 2121 stream->Add("{"); | |
| 2122 for (int i = 0; i < pointer_operands_.length(); ++i) { | |
| 2123 if (i != 0) stream->Add(";"); | |
| 2124 pointer_operands_[i]->PrintTo(stream); | |
| 2125 } | |
| 2126 stream->Add("} @%d", position()); | |
| 2127 } | |
| 2128 | |
| 2129 } } // namespace v8::internal | |
| OLD | NEW |