OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length(), zone()); | 126 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length(), zone()); |
127 for (int i = 0; i < environment->length(); i++) { | 127 for (int i = 0; i < environment->length(); i++) { |
128 HValue* val = environment->values()->at(i); | 128 HValue* val = environment->values()->at(i); |
129 instr->AddEnvironmentValue(val, zone()); | 129 instr->AddEnvironmentValue(val, zone()); |
130 } | 130 } |
131 | 131 |
132 return instr; | 132 return instr; |
133 } | 133 } |
134 | 134 |
135 | 135 |
136 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id) { | 136 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, |
| 137 RemovableSimulate removable) { |
137 ASSERT(HasEnvironment()); | 138 ASSERT(HasEnvironment()); |
138 HEnvironment* environment = last_environment(); | 139 HEnvironment* environment = last_environment(); |
139 ASSERT(ast_id.IsNone() || | 140 ASSERT(ast_id.IsNone() || |
140 environment->closure()->shared()->VerifyBailoutId(ast_id)); | 141 environment->closure()->shared()->VerifyBailoutId(ast_id)); |
141 | 142 |
142 int push_count = environment->push_count(); | 143 int push_count = environment->push_count(); |
143 int pop_count = environment->pop_count(); | 144 int pop_count = environment->pop_count(); |
144 | 145 |
145 HSimulate* instr = new(zone()) HSimulate(ast_id, pop_count, zone()); | 146 HSimulate* instr = |
146 for (int i = push_count - 1; i >= 0; --i) { | 147 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); |
| 148 // Order of pushed values: newest (top of stack) first. This allows |
| 149 // HSimulate::MergeInto() to easily append additional pushed values |
| 150 // that are older (from further down the stack). |
| 151 for (int i = 0; i < push_count; ++i) { |
147 instr->AddPushedValue(environment->ExpressionStackAt(i)); | 152 instr->AddPushedValue(environment->ExpressionStackAt(i)); |
148 } | 153 } |
149 for (int i = 0; i < environment->assigned_variables()->length(); ++i) { | 154 for (int i = 0; i < environment->assigned_variables()->length(); ++i) { |
150 int index = environment->assigned_variables()->at(i); | 155 int index = environment->assigned_variables()->at(i); |
151 instr->AddAssignedValue(index, environment->Lookup(index)); | 156 instr->AddAssignedValue(index, environment->Lookup(index)); |
152 } | 157 } |
153 environment->ClearHistory(); | 158 environment->ClearHistory(); |
154 return instr; | 159 return instr; |
155 } | 160 } |
156 | 161 |
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 Analyze(block->dominated_blocks()->at(i)); | 1289 Analyze(block->dominated_blocks()->at(i)); |
1285 } | 1290 } |
1286 | 1291 |
1287 RollBackTo(last_changed_range); | 1292 RollBackTo(last_changed_range); |
1288 } | 1293 } |
1289 | 1294 |
1290 | 1295 |
1291 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, | 1296 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, |
1292 HBasicBlock* dest) { | 1297 HBasicBlock* dest) { |
1293 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); | 1298 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); |
1294 if (test->GetInputRepresentation().IsInteger32()) { | 1299 if (test->representation().IsInteger32()) { |
1295 Token::Value op = test->token(); | 1300 Token::Value op = test->token(); |
1296 if (test->SecondSuccessor() == dest) { | 1301 if (test->SecondSuccessor() == dest) { |
1297 op = Token::NegateCompareOp(op); | 1302 op = Token::NegateCompareOp(op); |
1298 } | 1303 } |
1299 Token::Value inverted_op = Token::InvertCompareOp(op); | 1304 Token::Value inverted_op = Token::InvertCompareOp(op); |
1300 UpdateControlFlowRange(op, test->left(), test->right()); | 1305 UpdateControlFlowRange(op, test->left(), test->right()); |
1301 UpdateControlFlowRange(inverted_op, test->right(), test->left()); | 1306 UpdateControlFlowRange(inverted_op, test->right(), test->left()); |
1302 } | 1307 } |
1303 } | 1308 } |
1304 | 1309 |
(...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 dominated); | 2237 dominated); |
2233 successor_map->Kill(side_effects_on_all_paths); | 2238 successor_map->Kill(side_effects_on_all_paths); |
2234 successor_dominators->Kill(side_effects_on_all_paths); | 2239 successor_dominators->Kill(side_effects_on_all_paths); |
2235 } | 2240 } |
2236 } | 2241 } |
2237 current = next; | 2242 current = next; |
2238 } | 2243 } |
2239 } | 2244 } |
2240 | 2245 |
2241 | 2246 |
2242 class HInferRepresentation BASE_EMBEDDED { | |
2243 public: | |
2244 explicit HInferRepresentation(HGraph* graph) | |
2245 : graph_(graph), | |
2246 worklist_(8, graph->zone()), | |
2247 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { } | |
2248 | |
2249 void Analyze(); | |
2250 | |
2251 private: | |
2252 Representation TryChange(HValue* current); | |
2253 void AddToWorklist(HValue* current); | |
2254 void InferBasedOnInputs(HValue* current); | |
2255 void AddDependantsToWorklist(HValue* current); | |
2256 void InferBasedOnUses(HValue* current); | |
2257 | |
2258 Zone* zone() const { return graph_->zone(); } | |
2259 | |
2260 HGraph* graph_; | |
2261 ZoneList<HValue*> worklist_; | |
2262 BitVector in_worklist_; | |
2263 }; | |
2264 | |
2265 | |
2266 void HInferRepresentation::AddToWorklist(HValue* current) { | 2247 void HInferRepresentation::AddToWorklist(HValue* current) { |
2267 if (current->representation().IsSpecialization()) return; | 2248 if (current->representation().IsTagged()) return; |
2268 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; | 2249 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; |
2269 if (in_worklist_.Contains(current->id())) return; | 2250 if (in_worklist_.Contains(current->id())) return; |
2270 worklist_.Add(current, zone()); | 2251 worklist_.Add(current, zone()); |
2271 in_worklist_.Add(current->id()); | 2252 in_worklist_.Add(current->id()); |
2272 } | 2253 } |
2273 | 2254 |
2274 | 2255 |
2275 // This method tries to specialize the representation type of the value | |
2276 // given as a parameter. The value is asked to infer its representation type | |
2277 // based on its inputs. If the inferred type is more specialized, then this | |
2278 // becomes the new representation type of the node. | |
2279 void HInferRepresentation::InferBasedOnInputs(HValue* current) { | |
2280 Representation r = current->representation(); | |
2281 if (r.IsSpecialization()) return; | |
2282 ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); | |
2283 Representation inferred = current->InferredRepresentation(); | |
2284 if (inferred.IsSpecialization()) { | |
2285 if (FLAG_trace_representation) { | |
2286 PrintF("Changing #%d representation %s -> %s based on inputs\n", | |
2287 current->id(), | |
2288 r.Mnemonic(), | |
2289 inferred.Mnemonic()); | |
2290 } | |
2291 current->ChangeRepresentation(inferred); | |
2292 AddDependantsToWorklist(current); | |
2293 } | |
2294 } | |
2295 | |
2296 | |
2297 void HInferRepresentation::AddDependantsToWorklist(HValue* value) { | |
2298 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { | |
2299 AddToWorklist(it.value()); | |
2300 } | |
2301 for (int i = 0; i < value->OperandCount(); ++i) { | |
2302 AddToWorklist(value->OperandAt(i)); | |
2303 } | |
2304 } | |
2305 | |
2306 | |
2307 // This method calculates whether specializing the representation of the value | |
2308 // given as the parameter has a benefit in terms of less necessary type | |
2309 // conversions. If there is a benefit, then the representation of the value is | |
2310 // specialized. | |
2311 void HInferRepresentation::InferBasedOnUses(HValue* value) { | |
2312 Representation r = value->representation(); | |
2313 if (r.IsSpecialization() || value->HasNoUses()) return; | |
2314 ASSERT(value->CheckFlag(HValue::kFlexibleRepresentation)); | |
2315 Representation new_rep = TryChange(value); | |
2316 if (!new_rep.IsNone()) { | |
2317 if (!value->representation().Equals(new_rep)) { | |
2318 if (FLAG_trace_representation) { | |
2319 PrintF("Changing #%d representation %s -> %s based on uses\n", | |
2320 value->id(), | |
2321 r.Mnemonic(), | |
2322 new_rep.Mnemonic()); | |
2323 } | |
2324 value->ChangeRepresentation(new_rep); | |
2325 AddDependantsToWorklist(value); | |
2326 } | |
2327 } | |
2328 } | |
2329 | |
2330 | |
2331 Representation HInferRepresentation::TryChange(HValue* value) { | |
2332 // Array of use counts for each representation. | |
2333 int use_count[Representation::kNumRepresentations] = { 0 }; | |
2334 | |
2335 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { | |
2336 HValue* use = it.value(); | |
2337 Representation rep = use->ObservedInputRepresentation(it.index()); | |
2338 if (rep.IsNone()) continue; | |
2339 if (FLAG_trace_representation) { | |
2340 PrintF("%d %s is used by %d %s as %s\n", | |
2341 value->id(), | |
2342 value->Mnemonic(), | |
2343 use->id(), | |
2344 use->Mnemonic(), | |
2345 rep.Mnemonic()); | |
2346 } | |
2347 if (use->IsPhi()) HPhi::cast(use)->AddIndirectUsesTo(&use_count[0]); | |
2348 use_count[rep.kind()] += use->LoopWeight(); | |
2349 } | |
2350 int tagged_count = use_count[Representation::kTagged]; | |
2351 int double_count = use_count[Representation::kDouble]; | |
2352 int int32_count = use_count[Representation::kInteger32]; | |
2353 int non_tagged_count = double_count + int32_count; | |
2354 | |
2355 // If a non-loop phi has tagged uses, don't convert it to untagged. | |
2356 if (value->IsPhi() && !value->block()->IsLoopHeader() && tagged_count > 0) { | |
2357 return Representation::None(); | |
2358 } | |
2359 | |
2360 // Prefer unboxing over boxing, the latter is more expensive. | |
2361 if (tagged_count > non_tagged_count) return Representation::None(); | |
2362 | |
2363 // Prefer Integer32 over Double, if possible. | |
2364 if (int32_count > 0 && value->IsConvertibleToInteger()) { | |
2365 return Representation::Integer32(); | |
2366 } | |
2367 | |
2368 if (double_count > 0) return Representation::Double(); | |
2369 | |
2370 return Representation::None(); | |
2371 } | |
2372 | |
2373 | |
2374 void HInferRepresentation::Analyze() { | 2256 void HInferRepresentation::Analyze() { |
2375 HPhase phase("H_Infer representations", graph_); | 2257 HPhase phase("H_Infer representations", graph_); |
2376 | 2258 |
2377 // (1) Initialize bit vectors and count real uses. Each phi gets a | 2259 // (1) Initialize bit vectors and count real uses. Each phi gets a |
2378 // bit-vector of length <number of phis>. | 2260 // bit-vector of length <number of phis>. |
2379 const ZoneList<HPhi*>* phi_list = graph_->phi_list(); | 2261 const ZoneList<HPhi*>* phi_list = graph_->phi_list(); |
2380 int phi_count = phi_list->length(); | 2262 int phi_count = phi_list->length(); |
2381 ZoneList<BitVector*> connected_phis(phi_count, graph_->zone()); | 2263 ZoneList<BitVector*> connected_phis(phi_count, graph_->zone()); |
2382 for (int i = 0; i < phi_count; ++i) { | 2264 for (int i = 0; i < phi_count; ++i) { |
2383 phi_list->at(i)->InitRealUses(i); | 2265 phi_list->at(i)->InitRealUses(i); |
(...skipping 30 matching lines...) Expand all Loading... |
2414 for (int i = 0; i < phi_count; ++i) { | 2296 for (int i = 0; i < phi_count; ++i) { |
2415 HPhi* phi = phi_list->at(i); | 2297 HPhi* phi = phi_list->at(i); |
2416 bool cti = phi->AllOperandsConvertibleToInteger(); | 2298 bool cti = phi->AllOperandsConvertibleToInteger(); |
2417 if (cti) continue; | 2299 if (cti) continue; |
2418 | 2300 |
2419 for (BitVector::Iterator it(connected_phis.at(i)); | 2301 for (BitVector::Iterator it(connected_phis.at(i)); |
2420 !it.Done(); | 2302 !it.Done(); |
2421 it.Advance()) { | 2303 it.Advance()) { |
2422 HPhi* phi = phi_list->at(it.Current()); | 2304 HPhi* phi = phi_list->at(it.Current()); |
2423 phi->set_is_convertible_to_integer(false); | 2305 phi->set_is_convertible_to_integer(false); |
2424 phi->ResetInteger32Uses(); | |
2425 } | 2306 } |
2426 } | 2307 } |
2427 | 2308 |
2428 // (3b) Use the phi reachability information from step 2 to | 2309 // (3b) Use the phi reachability information from step 2 to |
2429 // sum up the non-phi use counts of all connected phis. | 2310 // sum up the non-phi use counts of all connected phis. |
2430 for (int i = 0; i < phi_count; ++i) { | 2311 for (int i = 0; i < phi_count; ++i) { |
2431 HPhi* phi = phi_list->at(i); | 2312 HPhi* phi = phi_list->at(i); |
2432 for (BitVector::Iterator it(connected_phis.at(i)); | 2313 for (BitVector::Iterator it(connected_phis.at(i)); |
2433 !it.Done(); | 2314 !it.Done(); |
2434 it.Advance()) { | 2315 it.Advance()) { |
(...skipping 15 matching lines...) Expand all Loading... |
2450 while (current != NULL) { | 2331 while (current != NULL) { |
2451 AddToWorklist(current); | 2332 AddToWorklist(current); |
2452 current = current->next(); | 2333 current = current->next(); |
2453 } | 2334 } |
2454 } | 2335 } |
2455 | 2336 |
2456 // Do a fixed point iteration, trying to improve representations | 2337 // Do a fixed point iteration, trying to improve representations |
2457 while (!worklist_.is_empty()) { | 2338 while (!worklist_.is_empty()) { |
2458 HValue* current = worklist_.RemoveLast(); | 2339 HValue* current = worklist_.RemoveLast(); |
2459 in_worklist_.Remove(current->id()); | 2340 in_worklist_.Remove(current->id()); |
2460 InferBasedOnInputs(current); | 2341 current->InferRepresentation(this); |
2461 InferBasedOnUses(current); | 2342 } |
| 2343 |
| 2344 // Lastly: any instruction that we don't have representation information |
| 2345 // for defaults to Tagged. |
| 2346 for (int i = 0; i < graph_->blocks()->length(); ++i) { |
| 2347 HBasicBlock* block = graph_->blocks()->at(i); |
| 2348 const ZoneList<HPhi*>* phis = block->phis(); |
| 2349 for (int j = 0; j < phis->length(); ++j) { |
| 2350 HPhi* phi = phis->at(j); |
| 2351 if (phi->representation().IsNone()) { |
| 2352 phi->ChangeRepresentation(Representation::Tagged()); |
| 2353 } |
| 2354 } |
| 2355 for (HInstruction* current = block->first(); |
| 2356 current != NULL; current = current->next()) { |
| 2357 if (current->representation().IsNone() && |
| 2358 current->CheckFlag(HInstruction::kFlexibleRepresentation)) { |
| 2359 current->ChangeRepresentation(Representation::Tagged()); |
| 2360 } |
| 2361 } |
2462 } | 2362 } |
2463 } | 2363 } |
2464 | 2364 |
| 2365 |
| 2366 void HGraph::MergeRemovableSimulates() { |
| 2367 for (int i = 0; i < blocks()->length(); ++i) { |
| 2368 HBasicBlock* block = blocks()->at(i); |
| 2369 // Always reset the folding candidate at the start of a block. |
| 2370 HSimulate* folding_candidate = NULL; |
| 2371 // Nasty heuristic: Never remove the first simulate in a block. This |
| 2372 // just so happens to have a beneficial effect on register allocation. |
| 2373 bool first = true; |
| 2374 for (HInstruction* current = block->first(); |
| 2375 current != NULL; current = current->next()) { |
| 2376 if (current->IsLeaveInlined()) { |
| 2377 // Never fold simulates from inlined environments into simulates |
| 2378 // in the outer environment. |
| 2379 // (Before each HEnterInlined, there is a non-foldable HSimulate |
| 2380 // anyway, so we get the barrier in the other direction for free.) |
| 2381 if (folding_candidate != NULL) { |
| 2382 folding_candidate->DeleteAndReplaceWith(NULL); |
| 2383 } |
| 2384 folding_candidate = NULL; |
| 2385 continue; |
| 2386 } |
| 2387 // If we have an HSimulate and a candidate, perform the folding. |
| 2388 if (!current->IsSimulate()) continue; |
| 2389 if (first) { |
| 2390 first = false; |
| 2391 continue; |
| 2392 } |
| 2393 HSimulate* current_simulate = HSimulate::cast(current); |
| 2394 if (folding_candidate != NULL) { |
| 2395 folding_candidate->MergeInto(current_simulate); |
| 2396 folding_candidate->DeleteAndReplaceWith(NULL); |
| 2397 folding_candidate = NULL; |
| 2398 } |
| 2399 // Check if the current simulate is a candidate for folding. |
| 2400 if (current_simulate->previous()->HasObservableSideEffects() && |
| 2401 !current_simulate->next()->IsSimulate()) { |
| 2402 continue; |
| 2403 } |
| 2404 if (!current_simulate->is_candidate_for_removal()) { |
| 2405 continue; |
| 2406 } |
| 2407 folding_candidate = current_simulate; |
| 2408 } |
| 2409 } |
| 2410 } |
| 2411 |
2465 | 2412 |
2466 void HGraph::InitializeInferredTypes() { | 2413 void HGraph::InitializeInferredTypes() { |
2467 HPhase phase("H_Inferring types", this); | 2414 HPhase phase("H_Inferring types", this); |
2468 InitializeInferredTypes(0, this->blocks_.length() - 1); | 2415 InitializeInferredTypes(0, this->blocks_.length() - 1); |
2469 } | 2416 } |
2470 | 2417 |
2471 | 2418 |
2472 void HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) { | 2419 void HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) { |
2473 for (int i = from_inclusive; i <= to_inclusive; ++i) { | 2420 for (int i = from_inclusive; i <= to_inclusive; ++i) { |
2474 HBasicBlock* block = blocks_[i]; | 2421 HBasicBlock* block = blocks_[i]; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2546 int use_index, | 2493 int use_index, |
2547 Representation to) { | 2494 Representation to) { |
2548 // Insert the representation change right before its use. For phi-uses we | 2495 // Insert the representation change right before its use. For phi-uses we |
2549 // insert at the end of the corresponding predecessor. | 2496 // insert at the end of the corresponding predecessor. |
2550 HInstruction* next = NULL; | 2497 HInstruction* next = NULL; |
2551 if (use_value->IsPhi()) { | 2498 if (use_value->IsPhi()) { |
2552 next = use_value->block()->predecessors()->at(use_index)->end(); | 2499 next = use_value->block()->predecessors()->at(use_index)->end(); |
2553 } else { | 2500 } else { |
2554 next = HInstruction::cast(use_value); | 2501 next = HInstruction::cast(use_value); |
2555 } | 2502 } |
2556 | |
2557 // For constants we try to make the representation change at compile | 2503 // For constants we try to make the representation change at compile |
2558 // time. When a representation change is not possible without loss of | 2504 // time. When a representation change is not possible without loss of |
2559 // information we treat constants like normal instructions and insert the | 2505 // information we treat constants like normal instructions and insert the |
2560 // change instructions for them. | 2506 // change instructions for them. |
2561 HInstruction* new_value = NULL; | 2507 HInstruction* new_value = NULL; |
2562 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); | 2508 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); |
2563 bool deoptimize_on_undefined = | 2509 bool deoptimize_on_undefined = |
2564 use_value->CheckFlag(HValue::kDeoptimizeOnUndefined); | 2510 use_value->CheckFlag(HValue::kDeoptimizeOnUndefined); |
2565 if (value->IsConstant()) { | 2511 if (value->IsConstant()) { |
2566 HConstant* constant = HConstant::cast(value); | 2512 HConstant* constant = HConstant::cast(value); |
2567 // Try to create a new copy of the constant with the new representation. | 2513 // Try to create a new copy of the constant with the new representation. |
2568 new_value = is_truncating | 2514 new_value = (is_truncating && to.IsInteger32()) |
2569 ? constant->CopyToTruncatedInt32(zone()) | 2515 ? constant->CopyToTruncatedInt32(zone()) |
2570 : constant->CopyToRepresentation(to, zone()); | 2516 : constant->CopyToRepresentation(to, zone()); |
2571 } | 2517 } |
2572 | 2518 |
2573 if (new_value == NULL) { | 2519 if (new_value == NULL) { |
2574 new_value = new(zone()) HChange(value, to, | 2520 new_value = new(zone()) HChange(value, to, |
2575 is_truncating, deoptimize_on_undefined); | 2521 is_truncating, deoptimize_on_undefined); |
2576 } | 2522 } |
2577 | 2523 |
2578 new_value->InsertBefore(next); | 2524 new_value->InsertBefore(next); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2618 if (phi->representation().IsInteger32()) { | 2564 if (phi->representation().IsInteger32()) { |
2619 phi->SetFlag(HValue::kTruncatingToInt32); | 2565 phi->SetFlag(HValue::kTruncatingToInt32); |
2620 } | 2566 } |
2621 } | 2567 } |
2622 bool change = true; | 2568 bool change = true; |
2623 while (change) { | 2569 while (change) { |
2624 change = false; | 2570 change = false; |
2625 for (int i = 0; i < phi_list()->length(); i++) { | 2571 for (int i = 0; i < phi_list()->length(); i++) { |
2626 HPhi* phi = phi_list()->at(i); | 2572 HPhi* phi = phi_list()->at(i); |
2627 if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; | 2573 if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; |
2628 if (!phi->CheckUsesForFlag(HValue::kTruncatingToInt32)) { | 2574 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
2629 phi->ClearFlag(HValue::kTruncatingToInt32); | 2575 // If a Phi is used as a non-truncating int32 or as a double, |
2630 change = true; | 2576 // clear its "truncating" flag. |
| 2577 HValue* use = it.value(); |
| 2578 Representation input_representation = |
| 2579 use->RequiredInputRepresentation(it.index()); |
| 2580 if ((input_representation.IsInteger32() && |
| 2581 !use->CheckFlag(HValue::kTruncatingToInt32)) || |
| 2582 input_representation.IsDouble()) { |
| 2583 if (FLAG_trace_representation) { |
| 2584 PrintF("#%d Phi is not truncating because of #%d %s\n", |
| 2585 phi->id(), it.value()->id(), it.value()->Mnemonic()); |
| 2586 } |
| 2587 phi->ClearFlag(HValue::kTruncatingToInt32); |
| 2588 change = true; |
| 2589 break; |
| 2590 } |
2631 } | 2591 } |
2632 } | 2592 } |
2633 } | 2593 } |
2634 | 2594 |
2635 for (int i = 0; i < blocks_.length(); ++i) { | 2595 for (int i = 0; i < blocks_.length(); ++i) { |
2636 // Process phi instructions first. | 2596 // Process phi instructions first. |
2637 const ZoneList<HPhi*>* phis = blocks_[i]->phis(); | 2597 const ZoneList<HPhi*>* phis = blocks_[i]->phis(); |
2638 for (int j = 0; j < phis->length(); j++) { | 2598 for (int j = 0; j < phis->length(); j++) { |
2639 InsertRepresentationChangesForValue(phis->at(j)); | 2599 InsertRepresentationChangesForValue(phis->at(j)); |
2640 } | 2600 } |
2641 | 2601 |
2642 // Process normal instructions. | 2602 // Process normal instructions. |
2643 HInstruction* current = blocks_[i]->first(); | 2603 HInstruction* current = blocks_[i]->first(); |
2644 while (current != NULL) { | 2604 while (current != NULL) { |
| 2605 HInstruction* next = current->next(); |
2645 InsertRepresentationChangesForValue(current); | 2606 InsertRepresentationChangesForValue(current); |
2646 current = current->next(); | 2607 current = next; |
2647 } | 2608 } |
2648 } | 2609 } |
2649 } | 2610 } |
2650 | 2611 |
2651 | 2612 |
2652 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { | 2613 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { |
2653 if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return; | 2614 if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return; |
2654 phi->SetFlag(HValue::kDeoptimizeOnUndefined); | 2615 phi->SetFlag(HValue::kDeoptimizeOnUndefined); |
2655 for (int i = 0; i < phi->OperandCount(); ++i) { | 2616 for (int i = 0; i < phi->OperandCount(); ++i) { |
2656 HValue* input = phi->OperandAt(i); | 2617 HValue* input = phi->OperandAt(i); |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3031 | 2992 |
3032 | 2993 |
3033 void TestContext::ReturnValue(HValue* value) { | 2994 void TestContext::ReturnValue(HValue* value) { |
3034 BuildBranch(value); | 2995 BuildBranch(value); |
3035 } | 2996 } |
3036 | 2997 |
3037 | 2998 |
3038 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2999 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
3039 ASSERT(!instr->IsControlInstruction()); | 3000 ASSERT(!instr->IsControlInstruction()); |
3040 owner()->AddInstruction(instr); | 3001 owner()->AddInstruction(instr); |
3041 if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); | 3002 if (instr->HasObservableSideEffects()) { |
| 3003 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 3004 } |
3042 } | 3005 } |
3043 | 3006 |
3044 | 3007 |
3045 void EffectContext::ReturnControl(HControlInstruction* instr, | 3008 void EffectContext::ReturnControl(HControlInstruction* instr, |
3046 BailoutId ast_id) { | 3009 BailoutId ast_id) { |
3047 ASSERT(!instr->HasObservableSideEffects()); | 3010 ASSERT(!instr->HasObservableSideEffects()); |
3048 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 3011 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
3049 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 3012 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
3050 instr->SetSuccessorAt(0, empty_true); | 3013 instr->SetSuccessorAt(0, empty_true); |
3051 instr->SetSuccessorAt(1, empty_false); | 3014 instr->SetSuccessorAt(1, empty_false); |
3052 owner()->current_block()->Finish(instr); | 3015 owner()->current_block()->Finish(instr); |
3053 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); | 3016 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); |
3054 owner()->set_current_block(join); | 3017 owner()->set_current_block(join); |
3055 } | 3018 } |
3056 | 3019 |
3057 | 3020 |
3058 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 3021 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
3059 ASSERT(!instr->IsControlInstruction()); | 3022 ASSERT(!instr->IsControlInstruction()); |
3060 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 3023 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
3061 return owner()->Bailout("bad value context for arguments object value"); | 3024 return owner()->Bailout("bad value context for arguments object value"); |
3062 } | 3025 } |
3063 owner()->AddInstruction(instr); | 3026 owner()->AddInstruction(instr); |
3064 owner()->Push(instr); | 3027 owner()->Push(instr); |
3065 if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); | 3028 if (instr->HasObservableSideEffects()) { |
| 3029 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 3030 } |
3066 } | 3031 } |
3067 | 3032 |
3068 | 3033 |
3069 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 3034 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
3070 ASSERT(!instr->HasObservableSideEffects()); | 3035 ASSERT(!instr->HasObservableSideEffects()); |
3071 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 3036 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
3072 return owner()->Bailout("bad value context for arguments object value"); | 3037 return owner()->Bailout("bad value context for arguments object value"); |
3073 } | 3038 } |
3074 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 3039 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
3075 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); | 3040 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); |
(...skipping 11 matching lines...) Expand all Loading... |
3087 | 3052 |
3088 | 3053 |
3089 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 3054 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
3090 ASSERT(!instr->IsControlInstruction()); | 3055 ASSERT(!instr->IsControlInstruction()); |
3091 HGraphBuilder* builder = owner(); | 3056 HGraphBuilder* builder = owner(); |
3092 builder->AddInstruction(instr); | 3057 builder->AddInstruction(instr); |
3093 // We expect a simulate after every expression with side effects, though | 3058 // We expect a simulate after every expression with side effects, though |
3094 // this one isn't actually needed (and wouldn't work if it were targeted). | 3059 // this one isn't actually needed (and wouldn't work if it were targeted). |
3095 if (instr->HasObservableSideEffects()) { | 3060 if (instr->HasObservableSideEffects()) { |
3096 builder->Push(instr); | 3061 builder->Push(instr); |
3097 builder->AddSimulate(ast_id); | 3062 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); |
3098 builder->Pop(); | 3063 builder->Pop(); |
3099 } | 3064 } |
3100 BuildBranch(instr); | 3065 BuildBranch(instr); |
3101 } | 3066 } |
3102 | 3067 |
3103 | 3068 |
3104 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 3069 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
3105 ASSERT(!instr->HasObservableSideEffects()); | 3070 ASSERT(!instr->HasObservableSideEffects()); |
3106 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 3071 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
3107 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 3072 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3314 const ZoneList<HPhi*>* phis = osr_loop_entry()->phis(); | 3279 const ZoneList<HPhi*>* phis = osr_loop_entry()->phis(); |
3315 for (int j = 0; j < phis->length(); j++) { | 3280 for (int j = 0; j < phis->length(); j++) { |
3316 HPhi* phi = phis->at(j); | 3281 HPhi* phi = phis->at(j); |
3317 osr_values()->at(phi->merged_index())->set_incoming_value(phi); | 3282 osr_values()->at(phi->merged_index())->set_incoming_value(phi); |
3318 } | 3283 } |
3319 } | 3284 } |
3320 | 3285 |
3321 HInferRepresentation rep(this); | 3286 HInferRepresentation rep(this); |
3322 rep.Analyze(); | 3287 rep.Analyze(); |
3323 | 3288 |
| 3289 // Remove HSimulate instructions that have turned out not to be needed |
| 3290 // after all by folding them into the following HSimulate. |
| 3291 // This must happen after inferring representations. |
| 3292 MergeRemovableSimulates(); |
| 3293 |
3324 MarkDeoptimizeOnUndefined(); | 3294 MarkDeoptimizeOnUndefined(); |
3325 InsertRepresentationChanges(); | 3295 InsertRepresentationChanges(); |
3326 | 3296 |
3327 InitializeInferredTypes(); | 3297 InitializeInferredTypes(); |
3328 | 3298 |
3329 // Must be performed before canonicalization to ensure that Canonicalize | 3299 // Must be performed before canonicalization to ensure that Canonicalize |
3330 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with | 3300 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with |
3331 // zero. | 3301 // zero. |
3332 ComputeSafeUint32Operations(); | 3302 ComputeSafeUint32Operations(); |
3333 | 3303 |
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3803 } | 3773 } |
3804 | 3774 |
3805 | 3775 |
3806 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 3776 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
3807 ASSERT(current_block() != NULL); | 3777 ASSERT(current_block() != NULL); |
3808 current_block()->AddInstruction(instr); | 3778 current_block()->AddInstruction(instr); |
3809 return instr; | 3779 return instr; |
3810 } | 3780 } |
3811 | 3781 |
3812 | 3782 |
3813 void HGraphBuilder::AddSimulate(BailoutId ast_id) { | 3783 void HGraphBuilder::AddSimulate(BailoutId ast_id, RemovableSimulate removable) { |
3814 ASSERT(current_block() != NULL); | 3784 ASSERT(current_block() != NULL); |
3815 current_block()->AddSimulate(ast_id); | 3785 current_block()->AddSimulate(ast_id, removable); |
3816 } | 3786 } |
3817 | 3787 |
3818 | 3788 |
3819 void HGraphBuilder::AddPhi(HPhi* instr) { | 3789 void HGraphBuilder::AddPhi(HPhi* instr) { |
3820 ASSERT(current_block() != NULL); | 3790 ASSERT(current_block() != NULL); |
3821 current_block()->AddPhi(instr); | 3791 current_block()->AddPhi(instr); |
3822 } | 3792 } |
3823 | 3793 |
3824 | 3794 |
3825 void HGraphBuilder::PushAndAdd(HInstruction* instr) { | 3795 void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4162 switch_type = SMI_SWITCH; | 4132 switch_type = SMI_SWITCH; |
4163 } else if (clause->label()->IsStringLiteral()) { | 4133 } else if (clause->label()->IsStringLiteral()) { |
4164 switch_type = STRING_SWITCH; | 4134 switch_type = STRING_SWITCH; |
4165 } else { | 4135 } else { |
4166 return Bailout("SwitchStatement: non-literal switch label"); | 4136 return Bailout("SwitchStatement: non-literal switch label"); |
4167 } | 4137 } |
4168 } else if ((switch_type == STRING_SWITCH && | 4138 } else if ((switch_type == STRING_SWITCH && |
4169 !clause->label()->IsStringLiteral()) || | 4139 !clause->label()->IsStringLiteral()) || |
4170 (switch_type == SMI_SWITCH && | 4140 (switch_type == SMI_SWITCH && |
4171 !clause->label()->IsSmiLiteral())) { | 4141 !clause->label()->IsSmiLiteral())) { |
4172 return Bailout("SwitchStatemnt: mixed label types are not supported"); | 4142 return Bailout("SwitchStatement: mixed label types are not supported"); |
4173 } | 4143 } |
4174 } | 4144 } |
4175 | 4145 |
4176 HUnaryControlInstruction* string_check = NULL; | 4146 HUnaryControlInstruction* string_check = NULL; |
4177 HBasicBlock* not_string_block = NULL; | 4147 HBasicBlock* not_string_block = NULL; |
4178 | 4148 |
4179 // Test switch's tag value if all clauses are string literals | 4149 // Test switch's tag value if all clauses are string literals |
4180 if (switch_type == STRING_SWITCH) { | 4150 if (switch_type == STRING_SWITCH) { |
4181 string_check = new(zone()) HIsStringAndBranch(tag_value); | 4151 string_check = new(zone()) HIsStringAndBranch(tag_value); |
4182 first_test_block = graph()->CreateBasicBlock(); | 4152 first_test_block = graph()->CreateBasicBlock(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4216 // account for invisible uses. | 4186 // account for invisible uses. |
4217 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | 4187 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); |
4218 set_current_block(NULL); | 4188 set_current_block(NULL); |
4219 break; | 4189 break; |
4220 } | 4190 } |
4221 | 4191 |
4222 HCompareIDAndBranch* compare_ = | 4192 HCompareIDAndBranch* compare_ = |
4223 new(zone()) HCompareIDAndBranch(tag_value, | 4193 new(zone()) HCompareIDAndBranch(tag_value, |
4224 label_value, | 4194 label_value, |
4225 Token::EQ_STRICT); | 4195 Token::EQ_STRICT); |
4226 compare_->SetInputRepresentation(Representation::Integer32()); | 4196 compare_->set_observed_input_representation( |
| 4197 Representation::Integer32(), Representation::Integer32()); |
4227 compare = compare_; | 4198 compare = compare_; |
4228 } else { | 4199 } else { |
4229 compare = new(zone()) HStringCompareAndBranch(context, tag_value, | 4200 compare = new(zone()) HStringCompareAndBranch(context, tag_value, |
4230 label_value, | 4201 label_value, |
4231 Token::EQ_STRICT); | 4202 Token::EQ_STRICT); |
4232 } | 4203 } |
4233 | 4204 |
4234 compare->SetSuccessorAt(0, body_block); | 4205 compare->SetSuccessorAt(0, body_block); |
4235 compare->SetSuccessorAt(1, next_test_block); | 4206 compare->SetSuccessorAt(1, next_test_block); |
4236 current_block()->Finish(compare); | 4207 current_block()->Finish(compare); |
4237 | 4208 |
4238 set_current_block(next_test_block); | 4209 set_current_block(next_test_block); |
4239 } | 4210 } |
4240 | 4211 |
4241 // Save the current block to use for the default or to join with the | 4212 // Save the current block to use for the default or to join with the |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4580 current_block()->Goto(loop_entry); | 4551 current_block()->Goto(loop_entry); |
4581 set_current_block(loop_entry); | 4552 set_current_block(loop_entry); |
4582 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4553 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
4583 | 4554 |
4584 HValue* index = environment()->ExpressionStackAt(0); | 4555 HValue* index = environment()->ExpressionStackAt(0); |
4585 HValue* limit = environment()->ExpressionStackAt(1); | 4556 HValue* limit = environment()->ExpressionStackAt(1); |
4586 | 4557 |
4587 // Check that we still have more keys. | 4558 // Check that we still have more keys. |
4588 HCompareIDAndBranch* compare_index = | 4559 HCompareIDAndBranch* compare_index = |
4589 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); | 4560 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); |
4590 compare_index->SetInputRepresentation(Representation::Integer32()); | 4561 compare_index->set_observed_input_representation( |
| 4562 Representation::Integer32(), Representation::Integer32()); |
4591 | 4563 |
4592 HBasicBlock* loop_body = graph()->CreateBasicBlock(); | 4564 HBasicBlock* loop_body = graph()->CreateBasicBlock(); |
4593 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); | 4565 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); |
4594 | 4566 |
4595 compare_index->SetSuccessorAt(0, loop_body); | 4567 compare_index->SetSuccessorAt(0, loop_body); |
4596 compare_index->SetSuccessorAt(1, loop_successor); | 4568 compare_index->SetSuccessorAt(1, loop_successor); |
4597 current_block()->Finish(compare_index); | 4569 current_block()->Finish(compare_index); |
4598 | 4570 |
4599 set_current_block(loop_successor); | 4571 set_current_block(loop_successor); |
4600 Drop(5); | 4572 Drop(5); |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4855 return Bailout("reference to a variable which requires dynamic lookup"); | 4827 return Bailout("reference to a variable which requires dynamic lookup"); |
4856 } | 4828 } |
4857 } | 4829 } |
4858 | 4830 |
4859 | 4831 |
4860 void HGraphBuilder::VisitLiteral(Literal* expr) { | 4832 void HGraphBuilder::VisitLiteral(Literal* expr) { |
4861 ASSERT(!HasStackOverflow()); | 4833 ASSERT(!HasStackOverflow()); |
4862 ASSERT(current_block() != NULL); | 4834 ASSERT(current_block() != NULL); |
4863 ASSERT(current_block()->HasPredecessor()); | 4835 ASSERT(current_block()->HasPredecessor()); |
4864 HConstant* instr = | 4836 HConstant* instr = |
4865 new(zone()) HConstant(expr->handle(), Representation::Tagged()); | 4837 new(zone()) HConstant(expr->handle(), Representation::None()); |
4866 return ast_context()->ReturnInstruction(instr, expr->id()); | 4838 return ast_context()->ReturnInstruction(instr, expr->id()); |
4867 } | 4839 } |
4868 | 4840 |
4869 | 4841 |
4870 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 4842 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
4871 ASSERT(!HasStackOverflow()); | 4843 ASSERT(!HasStackOverflow()); |
4872 ASSERT(current_block() != NULL); | 4844 ASSERT(current_block() != NULL); |
4873 ASSERT(current_block()->HasPredecessor()); | 4845 ASSERT(current_block()->HasPredecessor()); |
4874 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4846 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
4875 Handle<FixedArray> literals(closure->literals()); | 4847 Handle<FixedArray> literals(closure->literals()); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5092 Handle<JSFunction> setter; | 5064 Handle<JSFunction> setter; |
5093 Handle<JSObject> holder; | 5065 Handle<JSObject> holder; |
5094 ASSERT(!LookupSetter(map, name, &setter, &holder)); | 5066 ASSERT(!LookupSetter(map, name, &setter, &holder)); |
5095 #endif | 5067 #endif |
5096 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, | 5068 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, |
5097 name, | 5069 name, |
5098 value, | 5070 value, |
5099 map)); | 5071 map)); |
5100 } | 5072 } |
5101 AddInstruction(store); | 5073 AddInstruction(store); |
5102 if (store->HasObservableSideEffects()) AddSimulate(key->id()); | 5074 if (store->HasObservableSideEffects()) { |
| 5075 AddSimulate(key->id(), REMOVABLE_SIMULATE); |
| 5076 } |
5103 } else { | 5077 } else { |
5104 CHECK_ALIVE(VisitForEffect(value)); | 5078 CHECK_ALIVE(VisitForEffect(value)); |
5105 } | 5079 } |
5106 break; | 5080 break; |
5107 } | 5081 } |
5108 // Fall through. | 5082 // Fall through. |
5109 case ObjectLiteral::Property::PROTOTYPE: | 5083 case ObjectLiteral::Property::PROTOTYPE: |
5110 case ObjectLiteral::Property::SETTER: | 5084 case ObjectLiteral::Property::SETTER: |
5111 case ObjectLiteral::Property::GETTER: | 5085 case ObjectLiteral::Property::GETTER: |
5112 return Bailout("Object literal with complex property"); | 5086 return Bailout("Object literal with complex property"); |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5473 | 5447 |
5474 if (join != NULL) { | 5448 if (join != NULL) { |
5475 if (!ast_context()->IsEffect()) Push(value); | 5449 if (!ast_context()->IsEffect()) Push(value); |
5476 current_block()->Goto(join); | 5450 current_block()->Goto(join); |
5477 } else { | 5451 } else { |
5478 // The HSimulate for the store should not see the stored value in | 5452 // The HSimulate for the store should not see the stored value in |
5479 // effect contexts (it is not materialized at expr->id() in the | 5453 // effect contexts (it is not materialized at expr->id() in the |
5480 // unoptimized code). | 5454 // unoptimized code). |
5481 if (instr->HasObservableSideEffects()) { | 5455 if (instr->HasObservableSideEffects()) { |
5482 if (ast_context()->IsEffect()) { | 5456 if (ast_context()->IsEffect()) { |
5483 AddSimulate(expr->id()); | 5457 AddSimulate(expr->id(), REMOVABLE_SIMULATE); |
5484 } else { | 5458 } else { |
5485 Push(value); | 5459 Push(value); |
5486 AddSimulate(expr->id()); | 5460 AddSimulate(expr->id(), REMOVABLE_SIMULATE); |
5487 Drop(1); | 5461 Drop(1); |
5488 } | 5462 } |
5489 } | 5463 } |
5490 return ast_context()->ReturnValue(value); | 5464 return ast_context()->ReturnValue(value); |
5491 } | 5465 } |
5492 } | 5466 } |
5493 | 5467 |
5494 ASSERT(join != NULL); | 5468 ASSERT(join != NULL); |
5495 join->SetJoinId(expr->id()); | 5469 join->SetJoinId(expr->id()); |
5496 set_current_block(join); | 5470 set_current_block(join); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5546 Drop(2); | 5520 Drop(2); |
5547 return HandlePolymorphicStoreNamedField(expr, object, value, types, name); | 5521 return HandlePolymorphicStoreNamedField(expr, object, value, types, name); |
5548 } else { | 5522 } else { |
5549 Drop(2); | 5523 Drop(2); |
5550 instr = BuildStoreNamedGeneric(object, name, value); | 5524 instr = BuildStoreNamedGeneric(object, name, value); |
5551 } | 5525 } |
5552 | 5526 |
5553 Push(value); | 5527 Push(value); |
5554 instr->set_position(expr->position()); | 5528 instr->set_position(expr->position()); |
5555 AddInstruction(instr); | 5529 AddInstruction(instr); |
5556 if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 5530 if (instr->HasObservableSideEffects()) { |
| 5531 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5532 } |
5557 return ast_context()->ReturnValue(Pop()); | 5533 return ast_context()->ReturnValue(Pop()); |
5558 | 5534 |
5559 } else { | 5535 } else { |
5560 // Keyed store. | 5536 // Keyed store. |
5561 CHECK_ALIVE(VisitForValue(prop->key())); | 5537 CHECK_ALIVE(VisitForValue(prop->key())); |
5562 CHECK_ALIVE(VisitForValue(expr->value())); | 5538 CHECK_ALIVE(VisitForValue(expr->value())); |
5563 HValue* value = Pop(); | 5539 HValue* value = Pop(); |
5564 HValue* key = Pop(); | 5540 HValue* key = Pop(); |
5565 HValue* object = Pop(); | 5541 HValue* object = Pop(); |
5566 bool has_side_effects = false; | 5542 bool has_side_effects = false; |
5567 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 5543 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
5568 expr->position(), | 5544 expr->position(), |
5569 true, // is_store | 5545 true, // is_store |
5570 &has_side_effects); | 5546 &has_side_effects); |
5571 Push(value); | 5547 Push(value); |
5572 ASSERT(has_side_effects); // Stores always have side effects. | 5548 ASSERT(has_side_effects); // Stores always have side effects. |
5573 AddSimulate(expr->AssignmentId()); | 5549 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5574 return ast_context()->ReturnValue(Pop()); | 5550 return ast_context()->ReturnValue(Pop()); |
5575 } | 5551 } |
5576 } | 5552 } |
5577 | 5553 |
5578 | 5554 |
5579 // Because not every expression has a position and there is not common | 5555 // Because not every expression has a position and there is not common |
5580 // superclass of Assignment and CountOperation, we cannot just pass the | 5556 // superclass of Assignment and CountOperation, we cannot just pass the |
5581 // owning expression instead of position and ast_id separately. | 5557 // owning expression instead of position and ast_id separately. |
5582 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 5558 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
5583 HValue* value, | 5559 HValue* value, |
5584 int position, | 5560 int position, |
5585 BailoutId ast_id) { | 5561 BailoutId ast_id) { |
5586 LookupResult lookup(isolate()); | 5562 LookupResult lookup(isolate()); |
5587 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5563 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
5588 if (type == kUseCell) { | 5564 if (type == kUseCell) { |
5589 Handle<GlobalObject> global(info()->global_object()); | 5565 Handle<GlobalObject> global(info()->global_object()); |
5590 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5566 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
5591 HInstruction* instr = | 5567 HInstruction* instr = |
5592 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 5568 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
5593 instr->set_position(position); | 5569 instr->set_position(position); |
5594 AddInstruction(instr); | 5570 AddInstruction(instr); |
5595 if (instr->HasObservableSideEffects()) AddSimulate(ast_id); | 5571 if (instr->HasObservableSideEffects()) { |
| 5572 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 5573 } |
5596 } else { | 5574 } else { |
5597 HValue* context = environment()->LookupContext(); | 5575 HValue* context = environment()->LookupContext(); |
5598 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 5576 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
5599 AddInstruction(global_object); | 5577 AddInstruction(global_object); |
5600 HStoreGlobalGeneric* instr = | 5578 HStoreGlobalGeneric* instr = |
5601 new(zone()) HStoreGlobalGeneric(context, | 5579 new(zone()) HStoreGlobalGeneric(context, |
5602 global_object, | 5580 global_object, |
5603 var->name(), | 5581 var->name(), |
5604 value, | 5582 value, |
5605 function_strict_mode_flag()); | 5583 function_strict_mode_flag()); |
5606 instr->set_position(position); | 5584 instr->set_position(position); |
5607 AddInstruction(instr); | 5585 AddInstruction(instr); |
5608 ASSERT(instr->HasObservableSideEffects()); | 5586 ASSERT(instr->HasObservableSideEffects()); |
5609 if (instr->HasObservableSideEffects()) AddSimulate(ast_id); | 5587 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
5610 } | 5588 } |
5611 } | 5589 } |
5612 | 5590 |
5613 | 5591 |
5614 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5592 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
5615 Expression* target = expr->target(); | 5593 Expression* target = expr->target(); |
5616 VariableProxy* proxy = target->AsVariableProxy(); | 5594 VariableProxy* proxy = target->AsVariableProxy(); |
5617 Property* prop = target->AsProperty(); | 5595 Property* prop = target->AsProperty(); |
5618 ASSERT(proxy == NULL || prop == NULL); | 5596 ASSERT(proxy == NULL || prop == NULL); |
5619 | 5597 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5676 UNREACHABLE(); | 5654 UNREACHABLE(); |
5677 default: | 5655 default: |
5678 mode = HStoreContextSlot::kNoCheck; | 5656 mode = HStoreContextSlot::kNoCheck; |
5679 } | 5657 } |
5680 | 5658 |
5681 HValue* context = BuildContextChainWalk(var); | 5659 HValue* context = BuildContextChainWalk(var); |
5682 HStoreContextSlot* instr = | 5660 HStoreContextSlot* instr = |
5683 new(zone()) HStoreContextSlot(context, var->index(), mode, Top()); | 5661 new(zone()) HStoreContextSlot(context, var->index(), mode, Top()); |
5684 AddInstruction(instr); | 5662 AddInstruction(instr); |
5685 if (instr->HasObservableSideEffects()) { | 5663 if (instr->HasObservableSideEffects()) { |
5686 AddSimulate(expr->AssignmentId()); | 5664 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5687 } | 5665 } |
5688 break; | 5666 break; |
5689 } | 5667 } |
5690 | 5668 |
5691 case Variable::LOOKUP: | 5669 case Variable::LOOKUP: |
5692 return Bailout("compound assignment to lookup slot"); | 5670 return Bailout("compound assignment to lookup slot"); |
5693 } | 5671 } |
5694 return ast_context()->ReturnValue(Pop()); | 5672 return ast_context()->ReturnValue(Pop()); |
5695 | 5673 |
5696 } else if (prop != NULL) { | 5674 } else if (prop != NULL) { |
(...skipping 19 matching lines...) Expand all Loading... |
5716 Handle<JSObject> holder; | 5694 Handle<JSObject> holder; |
5717 if (LookupGetter(map, name, &getter, &holder)) { | 5695 if (LookupGetter(map, name, &getter, &holder)) { |
5718 load = BuildCallGetter(object, map, getter, holder); | 5696 load = BuildCallGetter(object, map, getter, holder); |
5719 } else { | 5697 } else { |
5720 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 5698 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
5721 } | 5699 } |
5722 } else { | 5700 } else { |
5723 load = BuildLoadNamedGeneric(object, name, prop); | 5701 load = BuildLoadNamedGeneric(object, name, prop); |
5724 } | 5702 } |
5725 PushAndAdd(load); | 5703 PushAndAdd(load); |
5726 if (load->HasObservableSideEffects()) AddSimulate(prop->LoadId()); | 5704 if (load->HasObservableSideEffects()) { |
| 5705 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
| 5706 } |
5727 | 5707 |
5728 CHECK_ALIVE(VisitForValue(expr->value())); | 5708 CHECK_ALIVE(VisitForValue(expr->value())); |
5729 HValue* right = Pop(); | 5709 HValue* right = Pop(); |
5730 HValue* left = Pop(); | 5710 HValue* left = Pop(); |
5731 | 5711 |
5732 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5712 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5733 PushAndAdd(instr); | 5713 PushAndAdd(instr); |
5734 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); | 5714 if (instr->HasObservableSideEffects()) { |
| 5715 AddSimulate(operation->id(), REMOVABLE_SIMULATE); |
| 5716 } |
5735 | 5717 |
5736 HInstruction* store; | 5718 HInstruction* store; |
5737 if (!monomorphic) { | 5719 if (!monomorphic) { |
5738 // If we don't know the monomorphic type, do a generic store. | 5720 // If we don't know the monomorphic type, do a generic store. |
5739 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr)); | 5721 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr)); |
5740 } else { | 5722 } else { |
5741 Handle<JSFunction> setter; | 5723 Handle<JSFunction> setter; |
5742 Handle<JSObject> holder; | 5724 Handle<JSObject> holder; |
5743 if (LookupSetter(map, name, &setter, &holder)) { | 5725 if (LookupSetter(map, name, &setter, &holder)) { |
5744 store = BuildCallSetter(object, instr, map, setter, holder); | 5726 store = BuildCallSetter(object, instr, map, setter, holder); |
5745 } else { | 5727 } else { |
5746 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, | 5728 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, |
5747 name, | 5729 name, |
5748 instr, | 5730 instr, |
5749 map)); | 5731 map)); |
5750 } | 5732 } |
5751 } | 5733 } |
5752 AddInstruction(store); | 5734 AddInstruction(store); |
5753 // Drop the simulated receiver and value. Return the value. | 5735 // Drop the simulated receiver and value. Return the value. |
5754 Drop(2); | 5736 Drop(2); |
5755 Push(instr); | 5737 Push(instr); |
5756 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 5738 if (store->HasObservableSideEffects()) { |
| 5739 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 5740 } |
5757 return ast_context()->ReturnValue(Pop()); | 5741 return ast_context()->ReturnValue(Pop()); |
5758 | 5742 |
5759 } else { | 5743 } else { |
5760 // Keyed property. | 5744 // Keyed property. |
5761 CHECK_ALIVE(VisitForValue(prop->obj())); | 5745 CHECK_ALIVE(VisitForValue(prop->obj())); |
5762 CHECK_ALIVE(VisitForValue(prop->key())); | 5746 CHECK_ALIVE(VisitForValue(prop->key())); |
5763 HValue* obj = environment()->ExpressionStackAt(1); | 5747 HValue* obj = environment()->ExpressionStackAt(1); |
5764 HValue* key = environment()->ExpressionStackAt(0); | 5748 HValue* key = environment()->ExpressionStackAt(0); |
5765 | 5749 |
5766 bool has_side_effects = false; | 5750 bool has_side_effects = false; |
5767 HValue* load = HandleKeyedElementAccess( | 5751 HValue* load = HandleKeyedElementAccess( |
5768 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 5752 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
5769 false, // is_store | 5753 false, // is_store |
5770 &has_side_effects); | 5754 &has_side_effects); |
5771 Push(load); | 5755 Push(load); |
5772 if (has_side_effects) AddSimulate(prop->LoadId()); | 5756 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
5773 | 5757 |
5774 | 5758 |
5775 CHECK_ALIVE(VisitForValue(expr->value())); | 5759 CHECK_ALIVE(VisitForValue(expr->value())); |
5776 HValue* right = Pop(); | 5760 HValue* right = Pop(); |
5777 HValue* left = Pop(); | 5761 HValue* left = Pop(); |
5778 | 5762 |
5779 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5763 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5780 PushAndAdd(instr); | 5764 PushAndAdd(instr); |
5781 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); | 5765 if (instr->HasObservableSideEffects()) { |
| 5766 AddSimulate(operation->id(), REMOVABLE_SIMULATE); |
| 5767 } |
5782 | 5768 |
5783 expr->RecordTypeFeedback(oracle(), zone()); | 5769 expr->RecordTypeFeedback(oracle(), zone()); |
5784 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), | 5770 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), |
5785 RelocInfo::kNoPosition, | 5771 RelocInfo::kNoPosition, |
5786 true, // is_store | 5772 true, // is_store |
5787 &has_side_effects); | 5773 &has_side_effects); |
5788 | 5774 |
5789 // Drop the simulated receiver, key, and value. Return the value. | 5775 // Drop the simulated receiver, key, and value. Return the value. |
5790 Drop(3); | 5776 Drop(3); |
5791 Push(instr); | 5777 Push(instr); |
5792 ASSERT(has_side_effects); // Stores always have side effects. | 5778 ASSERT(has_side_effects); // Stores always have side effects. |
5793 AddSimulate(expr->AssignmentId()); | 5779 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5794 return ast_context()->ReturnValue(Pop()); | 5780 return ast_context()->ReturnValue(Pop()); |
5795 } | 5781 } |
5796 | 5782 |
5797 } else { | 5783 } else { |
5798 return Bailout("invalid lhs in compound assignment"); | 5784 return Bailout("invalid lhs in compound assignment"); |
5799 } | 5785 } |
5800 } | 5786 } |
5801 | 5787 |
5802 | 5788 |
5803 void HGraphBuilder::VisitAssignment(Assignment* expr) { | 5789 void HGraphBuilder::VisitAssignment(Assignment* expr) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5906 ASSERT(expr->op() == Token::INIT_CONST); | 5892 ASSERT(expr->op() == Token::INIT_CONST); |
5907 | 5893 |
5908 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 5894 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
5909 } | 5895 } |
5910 | 5896 |
5911 HValue* context = BuildContextChainWalk(var); | 5897 HValue* context = BuildContextChainWalk(var); |
5912 HStoreContextSlot* instr = new(zone()) HStoreContextSlot( | 5898 HStoreContextSlot* instr = new(zone()) HStoreContextSlot( |
5913 context, var->index(), mode, Top()); | 5899 context, var->index(), mode, Top()); |
5914 AddInstruction(instr); | 5900 AddInstruction(instr); |
5915 if (instr->HasObservableSideEffects()) { | 5901 if (instr->HasObservableSideEffects()) { |
5916 AddSimulate(expr->AssignmentId()); | 5902 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5917 } | 5903 } |
5918 return ast_context()->ReturnValue(Pop()); | 5904 return ast_context()->ReturnValue(Pop()); |
5919 } | 5905 } |
5920 | 5906 |
5921 case Variable::LOOKUP: | 5907 case Variable::LOOKUP: |
5922 return Bailout("assignment to LOOKUP variable"); | 5908 return Bailout("assignment to LOOKUP variable"); |
5923 } | 5909 } |
5924 } else { | 5910 } else { |
5925 return Bailout("invalid left-hand side in assignment"); | 5911 return Bailout("invalid left-hand side in assignment"); |
5926 } | 5912 } |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6044 case EXTERNAL_PIXEL_ELEMENTS: { | 6030 case EXTERNAL_PIXEL_ELEMENTS: { |
6045 val = AddInstruction(new(zone()) HClampToUint8(val)); | 6031 val = AddInstruction(new(zone()) HClampToUint8(val)); |
6046 break; | 6032 break; |
6047 } | 6033 } |
6048 case EXTERNAL_BYTE_ELEMENTS: | 6034 case EXTERNAL_BYTE_ELEMENTS: |
6049 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 6035 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
6050 case EXTERNAL_SHORT_ELEMENTS: | 6036 case EXTERNAL_SHORT_ELEMENTS: |
6051 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 6037 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
6052 case EXTERNAL_INT_ELEMENTS: | 6038 case EXTERNAL_INT_ELEMENTS: |
6053 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | 6039 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
6054 if (!val->representation().IsInteger32()) { | |
6055 val = AddInstruction(new(zone()) HChange( | |
6056 val, | |
6057 Representation::Integer32(), | |
6058 true, // Truncate to int32. | |
6059 false)); // Don't deoptimize undefined (irrelevant here). | |
6060 } | |
6061 break; | 6040 break; |
6062 } | 6041 } |
6063 case EXTERNAL_FLOAT_ELEMENTS: | 6042 case EXTERNAL_FLOAT_ELEMENTS: |
6064 case EXTERNAL_DOUBLE_ELEMENTS: | 6043 case EXTERNAL_DOUBLE_ELEMENTS: |
6065 break; | 6044 break; |
6066 case FAST_SMI_ELEMENTS: | 6045 case FAST_SMI_ELEMENTS: |
6067 case FAST_ELEMENTS: | 6046 case FAST_ELEMENTS: |
6068 case FAST_DOUBLE_ELEMENTS: | 6047 case FAST_DOUBLE_ELEMENTS: |
6069 case FAST_HOLEY_SMI_ELEMENTS: | 6048 case FAST_HOLEY_SMI_ELEMENTS: |
6070 case FAST_HOLEY_ELEMENTS: | 6049 case FAST_HOLEY_ELEMENTS: |
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6671 HValue* key = Pop(); | 6650 HValue* key = Pop(); |
6672 HValue* obj = Pop(); | 6651 HValue* obj = Pop(); |
6673 | 6652 |
6674 bool has_side_effects = false; | 6653 bool has_side_effects = false; |
6675 HValue* load = HandleKeyedElementAccess( | 6654 HValue* load = HandleKeyedElementAccess( |
6676 obj, key, NULL, expr, expr->id(), expr->position(), | 6655 obj, key, NULL, expr, expr->id(), expr->position(), |
6677 false, // is_store | 6656 false, // is_store |
6678 &has_side_effects); | 6657 &has_side_effects); |
6679 if (has_side_effects) { | 6658 if (has_side_effects) { |
6680 if (ast_context()->IsEffect()) { | 6659 if (ast_context()->IsEffect()) { |
6681 AddSimulate(expr->id()); | 6660 AddSimulate(expr->id(), REMOVABLE_SIMULATE); |
6682 } else { | 6661 } else { |
6683 Push(load); | 6662 Push(load); |
6684 AddSimulate(expr->id()); | 6663 AddSimulate(expr->id(), REMOVABLE_SIMULATE); |
6685 Drop(1); | 6664 Drop(1); |
6686 } | 6665 } |
6687 } | 6666 } |
6688 return ast_context()->ReturnValue(load); | 6667 return ast_context()->ReturnValue(load); |
6689 } | 6668 } |
6690 instr->set_position(expr->position()); | 6669 instr->set_position(expr->position()); |
6691 return ast_context()->ReturnInstruction(instr, expr->id()); | 6670 return ast_context()->ReturnInstruction(instr, expr->id()); |
6692 } | 6671 } |
6693 | 6672 |
6694 | 6673 |
(...skipping 1228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7923 } | 7902 } |
7924 | 7903 |
7925 | 7904 |
7926 void HGraphBuilder::VisitSub(UnaryOperation* expr) { | 7905 void HGraphBuilder::VisitSub(UnaryOperation* expr) { |
7927 CHECK_ALIVE(VisitForValue(expr->expression())); | 7906 CHECK_ALIVE(VisitForValue(expr->expression())); |
7928 HValue* value = Pop(); | 7907 HValue* value = Pop(); |
7929 HValue* context = environment()->LookupContext(); | 7908 HValue* context = environment()->LookupContext(); |
7930 HInstruction* instr = | 7909 HInstruction* instr = |
7931 new(zone()) HMul(context, value, graph_->GetConstantMinus1()); | 7910 new(zone()) HMul(context, value, graph_->GetConstantMinus1()); |
7932 TypeInfo info = oracle()->UnaryType(expr); | 7911 TypeInfo info = oracle()->UnaryType(expr); |
| 7912 Representation rep = ToRepresentation(info); |
7933 if (info.IsUninitialized()) { | 7913 if (info.IsUninitialized()) { |
7934 AddInstruction(new(zone()) HSoftDeoptimize); | 7914 AddInstruction(new(zone()) HSoftDeoptimize); |
7935 current_block()->MarkAsDeoptimizing(); | 7915 current_block()->MarkAsDeoptimizing(); |
7936 info = TypeInfo::Unknown(); | 7916 info = TypeInfo::Unknown(); |
7937 } | 7917 } |
7938 Representation rep = ToRepresentation(info); | 7918 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); |
7939 TraceRepresentation(expr->op(), info, instr, rep); | |
7940 instr->AssumeRepresentation(rep); | |
7941 return ast_context()->ReturnInstruction(instr, expr->id()); | 7919 return ast_context()->ReturnInstruction(instr, expr->id()); |
7942 } | 7920 } |
7943 | 7921 |
7944 | 7922 |
7945 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 7923 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
7946 CHECK_ALIVE(VisitForValue(expr->expression())); | 7924 CHECK_ALIVE(VisitForValue(expr->expression())); |
7947 HValue* value = Pop(); | 7925 HValue* value = Pop(); |
7948 TypeInfo info = oracle()->UnaryType(expr); | 7926 TypeInfo info = oracle()->UnaryType(expr); |
7949 if (info.IsUninitialized()) { | 7927 if (info.IsUninitialized()) { |
7950 AddInstruction(new(zone()) HSoftDeoptimize); | 7928 AddInstruction(new(zone()) HSoftDeoptimize); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8019 } | 7997 } |
8020 | 7998 |
8021 // The addition has no side effects, so we do not need | 7999 // The addition has no side effects, so we do not need |
8022 // to simulate the expression stack after this instruction. | 8000 // to simulate the expression stack after this instruction. |
8023 // Any later failures deopt to the load of the input or earlier. | 8001 // Any later failures deopt to the load of the input or earlier. |
8024 HConstant* delta = (expr->op() == Token::INC) | 8002 HConstant* delta = (expr->op() == Token::INC) |
8025 ? graph_->GetConstant1() | 8003 ? graph_->GetConstant1() |
8026 : graph_->GetConstantMinus1(); | 8004 : graph_->GetConstantMinus1(); |
8027 HValue* context = environment()->LookupContext(); | 8005 HValue* context = environment()->LookupContext(); |
8028 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); | 8006 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); |
8029 TraceRepresentation(expr->op(), info, instr, rep); | 8007 // We can't insert a simulate here, because it would break deoptimization, |
| 8008 // so the HAdd must not have side effects, so we must freeze its |
| 8009 // representation. |
8030 instr->AssumeRepresentation(rep); | 8010 instr->AssumeRepresentation(rep); |
| 8011 instr->ClearAllSideEffects(); |
8031 AddInstruction(instr); | 8012 AddInstruction(instr); |
8032 return instr; | 8013 return instr; |
8033 } | 8014 } |
8034 | 8015 |
8035 | 8016 |
8036 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { | 8017 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
8037 ASSERT(!HasStackOverflow()); | 8018 ASSERT(!HasStackOverflow()); |
8038 ASSERT(current_block() != NULL); | 8019 ASSERT(current_block() != NULL); |
8039 ASSERT(current_block()->HasPredecessor()); | 8020 ASSERT(current_block()->HasPredecessor()); |
8040 Expression* target = expr->expression(); | 8021 Expression* target = expr->expression(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8094 } | 8075 } |
8095 } | 8076 } |
8096 | 8077 |
8097 HValue* context = BuildContextChainWalk(var); | 8078 HValue* context = BuildContextChainWalk(var); |
8098 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 8079 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
8099 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 8080 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
8100 HStoreContextSlot* instr = | 8081 HStoreContextSlot* instr = |
8101 new(zone()) HStoreContextSlot(context, var->index(), mode, after); | 8082 new(zone()) HStoreContextSlot(context, var->index(), mode, after); |
8102 AddInstruction(instr); | 8083 AddInstruction(instr); |
8103 if (instr->HasObservableSideEffects()) { | 8084 if (instr->HasObservableSideEffects()) { |
8104 AddSimulate(expr->AssignmentId()); | 8085 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
8105 } | 8086 } |
8106 break; | 8087 break; |
8107 } | 8088 } |
8108 | 8089 |
8109 case Variable::LOOKUP: | 8090 case Variable::LOOKUP: |
8110 return Bailout("lookup variable in count operation"); | 8091 return Bailout("lookup variable in count operation"); |
8111 } | 8092 } |
8112 | 8093 |
8113 } else { | 8094 } else { |
8114 // Argument of the count operation is a property. | 8095 // Argument of the count operation is a property. |
(...skipping 20 matching lines...) Expand all Loading... |
8135 Handle<JSObject> holder; | 8116 Handle<JSObject> holder; |
8136 if (LookupGetter(map, name, &getter, &holder)) { | 8117 if (LookupGetter(map, name, &getter, &holder)) { |
8137 load = BuildCallGetter(object, map, getter, holder); | 8118 load = BuildCallGetter(object, map, getter, holder); |
8138 } else { | 8119 } else { |
8139 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 8120 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
8140 } | 8121 } |
8141 } else { | 8122 } else { |
8142 load = BuildLoadNamedGeneric(object, name, prop); | 8123 load = BuildLoadNamedGeneric(object, name, prop); |
8143 } | 8124 } |
8144 PushAndAdd(load); | 8125 PushAndAdd(load); |
8145 if (load->HasObservableSideEffects()) AddSimulate(prop->LoadId()); | 8126 if (load->HasObservableSideEffects()) { |
| 8127 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
| 8128 } |
8146 | 8129 |
8147 after = BuildIncrement(returns_original_input, expr); | 8130 after = BuildIncrement(returns_original_input, expr); |
8148 input = Pop(); | 8131 input = Pop(); |
8149 | 8132 |
8150 HInstruction* store; | 8133 HInstruction* store; |
8151 if (!monomorphic) { | 8134 if (!monomorphic) { |
8152 // If we don't know the monomorphic type, do a generic store. | 8135 // If we don't know the monomorphic type, do a generic store. |
8153 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after)); | 8136 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after)); |
8154 } else { | 8137 } else { |
8155 Handle<JSFunction> setter; | 8138 Handle<JSFunction> setter; |
8156 Handle<JSObject> holder; | 8139 Handle<JSObject> holder; |
8157 if (LookupSetter(map, name, &setter, &holder)) { | 8140 if (LookupSetter(map, name, &setter, &holder)) { |
8158 store = BuildCallSetter(object, after, map, setter, holder); | 8141 store = BuildCallSetter(object, after, map, setter, holder); |
8159 } else { | 8142 } else { |
8160 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, | 8143 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, |
8161 name, | 8144 name, |
8162 after, | 8145 after, |
8163 map)); | 8146 map)); |
8164 } | 8147 } |
8165 } | 8148 } |
8166 AddInstruction(store); | 8149 AddInstruction(store); |
8167 | 8150 |
8168 // Overwrite the receiver in the bailout environment with the result | 8151 // Overwrite the receiver in the bailout environment with the result |
8169 // of the operation, and the placeholder with the original value if | 8152 // of the operation, and the placeholder with the original value if |
8170 // necessary. | 8153 // necessary. |
8171 environment()->SetExpressionStackAt(0, after); | 8154 environment()->SetExpressionStackAt(0, after); |
8172 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 8155 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
8173 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 8156 if (store->HasObservableSideEffects()) { |
| 8157 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 8158 } |
8174 | 8159 |
8175 } else { | 8160 } else { |
8176 // Keyed property. | 8161 // Keyed property. |
8177 if (returns_original_input) Push(graph_->GetConstantUndefined()); | 8162 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
8178 | 8163 |
8179 CHECK_ALIVE(VisitForValue(prop->obj())); | 8164 CHECK_ALIVE(VisitForValue(prop->obj())); |
8180 CHECK_ALIVE(VisitForValue(prop->key())); | 8165 CHECK_ALIVE(VisitForValue(prop->key())); |
8181 HValue* obj = environment()->ExpressionStackAt(1); | 8166 HValue* obj = environment()->ExpressionStackAt(1); |
8182 HValue* key = environment()->ExpressionStackAt(0); | 8167 HValue* key = environment()->ExpressionStackAt(0); |
8183 | 8168 |
8184 bool has_side_effects = false; | 8169 bool has_side_effects = false; |
8185 HValue* load = HandleKeyedElementAccess( | 8170 HValue* load = HandleKeyedElementAccess( |
8186 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 8171 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
8187 false, // is_store | 8172 false, // is_store |
8188 &has_side_effects); | 8173 &has_side_effects); |
8189 Push(load); | 8174 Push(load); |
8190 if (has_side_effects) AddSimulate(prop->LoadId()); | 8175 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
8191 | 8176 |
8192 after = BuildIncrement(returns_original_input, expr); | 8177 after = BuildIncrement(returns_original_input, expr); |
8193 input = Pop(); | 8178 input = Pop(); |
8194 | 8179 |
8195 expr->RecordTypeFeedback(oracle(), zone()); | 8180 expr->RecordTypeFeedback(oracle(), zone()); |
8196 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), | 8181 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), |
8197 RelocInfo::kNoPosition, | 8182 RelocInfo::kNoPosition, |
8198 true, // is_store | 8183 true, // is_store |
8199 &has_side_effects); | 8184 &has_side_effects); |
8200 | 8185 |
8201 // Drop the key from the bailout environment. Overwrite the receiver | 8186 // Drop the key from the bailout environment. Overwrite the receiver |
8202 // with the result of the operation, and the placeholder with the | 8187 // with the result of the operation, and the placeholder with the |
8203 // original value if necessary. | 8188 // original value if necessary. |
8204 Drop(1); | 8189 Drop(1); |
8205 environment()->SetExpressionStackAt(0, after); | 8190 environment()->SetExpressionStackAt(0, after); |
8206 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 8191 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
8207 ASSERT(has_side_effects); // Stores always have side effects. | 8192 ASSERT(has_side_effects); // Stores always have side effects. |
8208 AddSimulate(expr->AssignmentId()); | 8193 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
8209 } | 8194 } |
8210 } | 8195 } |
8211 | 8196 |
8212 Drop(returns_original_input ? 2 : 1); | 8197 Drop(returns_original_input ? 2 : 1); |
8213 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 8198 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
8214 } | 8199 } |
8215 | 8200 |
8216 | 8201 |
8217 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, | 8202 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, |
8218 HValue* string, | 8203 HValue* string, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8279 } | 8264 } |
8280 } | 8265 } |
8281 return true; | 8266 return true; |
8282 } | 8267 } |
8283 | 8268 |
8284 | 8269 |
8285 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, | 8270 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
8286 HValue* left, | 8271 HValue* left, |
8287 HValue* right) { | 8272 HValue* right) { |
8288 HValue* context = environment()->LookupContext(); | 8273 HValue* context = environment()->LookupContext(); |
8289 TypeInfo info = oracle()->BinaryType(expr); | 8274 TypeInfo left_info, right_info, result_info, combined_info; |
8290 if (info.IsUninitialized()) { | 8275 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); |
| 8276 Representation left_rep = ToRepresentation(left_info); |
| 8277 Representation right_rep = ToRepresentation(right_info); |
| 8278 Representation result_rep = ToRepresentation(result_info); |
| 8279 if (left_info.IsUninitialized()) { |
| 8280 // Can't have initialized one but not the other. |
| 8281 ASSERT(right_info.IsUninitialized()); |
8291 AddInstruction(new(zone()) HSoftDeoptimize); | 8282 AddInstruction(new(zone()) HSoftDeoptimize); |
8292 current_block()->MarkAsDeoptimizing(); | 8283 current_block()->MarkAsDeoptimizing(); |
8293 info = TypeInfo::Unknown(); | 8284 left_info = right_info = TypeInfo::Unknown(); |
8294 } | 8285 } |
8295 HInstruction* instr = NULL; | 8286 HInstruction* instr = NULL; |
8296 switch (expr->op()) { | 8287 switch (expr->op()) { |
8297 case Token::ADD: | 8288 case Token::ADD: |
8298 if (info.IsString()) { | 8289 if (left_info.IsString() && right_info.IsString()) { |
8299 AddInstruction(new(zone()) HCheckNonSmi(left)); | 8290 AddInstruction(new(zone()) HCheckNonSmi(left)); |
8300 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 8291 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
8301 AddInstruction(new(zone()) HCheckNonSmi(right)); | 8292 AddInstruction(new(zone()) HCheckNonSmi(right)); |
8302 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 8293 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
8303 instr = new(zone()) HStringAdd(context, left, right); | 8294 instr = new(zone()) HStringAdd(context, left, right); |
8304 } else { | 8295 } else { |
8305 instr = HAdd::NewHAdd(zone(), context, left, right); | 8296 instr = HAdd::NewHAdd(zone(), context, left, right); |
8306 } | 8297 } |
8307 break; | 8298 break; |
8308 case Token::SUB: | 8299 case Token::SUB: |
8309 instr = HSub::NewHSub(zone(), context, left, right); | 8300 instr = HSub::NewHSub(zone(), context, left, right); |
8310 break; | 8301 break; |
8311 case Token::MUL: | 8302 case Token::MUL: |
8312 instr = HMul::NewHMul(zone(), context, left, right); | 8303 instr = HMul::NewHMul(zone(), context, left, right); |
8313 break; | 8304 break; |
8314 case Token::MOD: | 8305 case Token::MOD: |
8315 instr = HMod::NewHMod(zone(), context, left, right); | 8306 instr = HMod::NewHMod(zone(), context, left, right); |
8316 break; | 8307 break; |
8317 case Token::DIV: | 8308 case Token::DIV: |
8318 instr = HDiv::NewHDiv(zone(), context, left, right); | 8309 instr = HDiv::NewHDiv(zone(), context, left, right); |
8319 break; | 8310 break; |
8320 case Token::BIT_XOR: | 8311 case Token::BIT_XOR: |
8321 case Token::BIT_AND: | 8312 case Token::BIT_AND: |
8322 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); | 8313 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); |
8323 break; | 8314 break; |
8324 case Token::BIT_OR: { | 8315 case Token::BIT_OR: { |
8325 HValue* operand, *shift_amount; | 8316 HValue* operand, *shift_amount; |
8326 if (info.IsInteger32() && | 8317 if (left_info.IsInteger32() && right_info.IsInteger32() && |
8327 MatchRotateRight(left, right, &operand, &shift_amount)) { | 8318 MatchRotateRight(left, right, &operand, &shift_amount)) { |
8328 instr = new(zone()) HRor(context, operand, shift_amount); | 8319 instr = new(zone()) HRor(context, operand, shift_amount); |
8329 } else { | 8320 } else { |
8330 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); | 8321 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); |
8331 } | 8322 } |
8332 break; | 8323 break; |
8333 } | 8324 } |
8334 case Token::SAR: | 8325 case Token::SAR: |
8335 instr = HSar::NewHSar(zone(), context, left, right); | 8326 instr = HSar::NewHSar(zone(), context, left, right); |
8336 break; | 8327 break; |
8337 case Token::SHR: | 8328 case Token::SHR: |
8338 instr = HShr::NewHShr(zone(), context, left, right); | 8329 instr = HShr::NewHShr(zone(), context, left, right); |
8339 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | 8330 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
8340 CanBeZero(right)) { | 8331 CanBeZero(right)) { |
8341 graph()->RecordUint32Instruction(instr); | 8332 graph()->RecordUint32Instruction(instr); |
8342 } | 8333 } |
8343 break; | 8334 break; |
8344 case Token::SHL: | 8335 case Token::SHL: |
8345 instr = HShl::NewHShl(zone(), context, left, right); | 8336 instr = HShl::NewHShl(zone(), context, left, right); |
8346 break; | 8337 break; |
8347 default: | 8338 default: |
8348 UNREACHABLE(); | 8339 UNREACHABLE(); |
8349 } | 8340 } |
8350 | 8341 |
8351 // If we hit an uninitialized binary op stub we will get type info | 8342 if (instr->IsBinaryOperation()) { |
8352 // for a smi operation. If one of the operands is a constant string | 8343 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
8353 // do not generate code assuming it is a smi operation. | 8344 binop->set_observed_input_representation(left_rep, right_rep); |
8354 if (info.IsSmi() && | 8345 binop->initialize_output_representation(result_rep); |
8355 ((left->IsConstant() && HConstant::cast(left)->handle()->IsString()) || | |
8356 (right->IsConstant() && HConstant::cast(right)->handle()->IsString()))) { | |
8357 return instr; | |
8358 } | 8346 } |
8359 Representation rep = ToRepresentation(info); | |
8360 // We only generate either int32 or generic tagged bitwise operations. | |
8361 if (instr->IsBitwiseBinaryOperation()) { | |
8362 HBitwiseBinaryOperation::cast(instr)-> | |
8363 InitializeObservedInputRepresentation(rep); | |
8364 if (rep.IsDouble()) rep = Representation::Integer32(); | |
8365 } | |
8366 TraceRepresentation(expr->op(), info, instr, rep); | |
8367 instr->AssumeRepresentation(rep); | |
8368 return instr; | 8347 return instr; |
8369 } | 8348 } |
8370 | 8349 |
8371 | 8350 |
8372 // Check for the form (%_ClassOf(foo) === 'BarClass'). | 8351 // Check for the form (%_ClassOf(foo) === 'BarClass'). |
8373 static bool IsClassOfTest(CompareOperation* expr) { | 8352 static bool IsClassOfTest(CompareOperation* expr) { |
8374 if (expr->op() != Token::EQ_STRICT) return false; | 8353 if (expr->op() != Token::EQ_STRICT) return false; |
8375 CallRuntime* call = expr->left()->AsCallRuntime(); | 8354 CallRuntime* call = expr->left()->AsCallRuntime(); |
8376 if (call == NULL) return false; | 8355 if (call == NULL) return false; |
8377 Literal* literal = expr->right()->AsLiteral(); | 8356 Literal* literal = expr->right()->AsLiteral(); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8501 CHECK_ALIVE(VisitForValue(expr->left())); | 8480 CHECK_ALIVE(VisitForValue(expr->left())); |
8502 CHECK_ALIVE(VisitForValue(expr->right())); | 8481 CHECK_ALIVE(VisitForValue(expr->right())); |
8503 HValue* right = Pop(); | 8482 HValue* right = Pop(); |
8504 HValue* left = Pop(); | 8483 HValue* left = Pop(); |
8505 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8484 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
8506 instr->set_position(expr->position()); | 8485 instr->set_position(expr->position()); |
8507 return ast_context()->ReturnInstruction(instr, expr->id()); | 8486 return ast_context()->ReturnInstruction(instr, expr->id()); |
8508 } | 8487 } |
8509 | 8488 |
8510 | 8489 |
8511 void HGraphBuilder::TraceRepresentation(Token::Value op, | |
8512 TypeInfo info, | |
8513 HValue* value, | |
8514 Representation rep) { | |
8515 if (!FLAG_trace_representation) return; | |
8516 // TODO(svenpanne) Under which circumstances are we actually not flexible? | |
8517 // At first glance, this looks a bit weird... | |
8518 bool flexible = value->CheckFlag(HValue::kFlexibleRepresentation); | |
8519 PrintF("Operation %s has type info %s, %schange representation assumption " | |
8520 "for %s (ID %d) from %s to %s\n", | |
8521 Token::Name(op), | |
8522 info.ToString(), | |
8523 flexible ? "" : " DO NOT ", | |
8524 value->Mnemonic(), | |
8525 graph_->GetMaximumValueID(), | |
8526 value->representation().Mnemonic(), | |
8527 rep.Mnemonic()); | |
8528 } | |
8529 | |
8530 | |
8531 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { | 8490 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { |
| 8491 if (info.IsUninitialized()) return Representation::None(); |
8532 if (info.IsSmi()) return Representation::Integer32(); | 8492 if (info.IsSmi()) return Representation::Integer32(); |
8533 if (info.IsInteger32()) return Representation::Integer32(); | 8493 if (info.IsInteger32()) return Representation::Integer32(); |
8534 if (info.IsDouble()) return Representation::Double(); | 8494 if (info.IsDouble()) return Representation::Double(); |
8535 if (info.IsNumber()) return Representation::Double(); | 8495 if (info.IsNumber()) return Representation::Double(); |
8536 return Representation::Tagged(); | 8496 return Representation::Tagged(); |
8537 } | 8497 } |
8538 | 8498 |
8539 | 8499 |
8540 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8500 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
8541 HTypeof* typeof_expr, | 8501 HTypeof* typeof_expr, |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8619 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8579 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8620 HValue* value = Pop(); | 8580 HValue* value = Pop(); |
8621 Literal* literal = expr->right()->AsLiteral(); | 8581 Literal* literal = expr->right()->AsLiteral(); |
8622 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 8582 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
8623 HClassOfTestAndBranch* instr = | 8583 HClassOfTestAndBranch* instr = |
8624 new(zone()) HClassOfTestAndBranch(value, rhs); | 8584 new(zone()) HClassOfTestAndBranch(value, rhs); |
8625 instr->set_position(expr->position()); | 8585 instr->set_position(expr->position()); |
8626 return ast_context()->ReturnControl(instr, expr->id()); | 8586 return ast_context()->ReturnControl(instr, expr->id()); |
8627 } | 8587 } |
8628 | 8588 |
8629 TypeInfo type_info = oracle()->CompareType(expr); | 8589 TypeInfo left_type, right_type, overall_type_info; |
| 8590 oracle()->CompareType(expr, &left_type, &right_type, &overall_type_info); |
| 8591 Representation combined_rep = ToRepresentation(overall_type_info); |
| 8592 Representation left_rep = ToRepresentation(left_type); |
| 8593 Representation right_rep = ToRepresentation(right_type); |
8630 // Check if this expression was ever executed according to type feedback. | 8594 // Check if this expression was ever executed according to type feedback. |
8631 // Note that for the special typeof/null/undefined cases we get unknown here. | 8595 // Note that for the special typeof/null/undefined cases we get unknown here. |
8632 if (type_info.IsUninitialized()) { | 8596 if (overall_type_info.IsUninitialized()) { |
8633 AddInstruction(new(zone()) HSoftDeoptimize); | 8597 AddInstruction(new(zone()) HSoftDeoptimize); |
8634 current_block()->MarkAsDeoptimizing(); | 8598 current_block()->MarkAsDeoptimizing(); |
8635 type_info = TypeInfo::Unknown(); | 8599 overall_type_info = left_type = right_type = TypeInfo::Unknown(); |
8636 } | 8600 } |
8637 | 8601 |
8638 CHECK_ALIVE(VisitForValue(expr->left())); | 8602 CHECK_ALIVE(VisitForValue(expr->left())); |
8639 CHECK_ALIVE(VisitForValue(expr->right())); | 8603 CHECK_ALIVE(VisitForValue(expr->right())); |
8640 | 8604 |
8641 HValue* context = environment()->LookupContext(); | 8605 HValue* context = environment()->LookupContext(); |
8642 HValue* right = Pop(); | 8606 HValue* right = Pop(); |
8643 HValue* left = Pop(); | 8607 HValue* left = Pop(); |
8644 Token::Value op = expr->op(); | 8608 Token::Value op = expr->op(); |
8645 | 8609 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8697 AddInstruction(new(zone()) HCheckFunction(right, target)); | 8661 AddInstruction(new(zone()) HCheckFunction(right, target)); |
8698 HInstanceOfKnownGlobal* result = | 8662 HInstanceOfKnownGlobal* result = |
8699 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 8663 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
8700 result->set_position(expr->position()); | 8664 result->set_position(expr->position()); |
8701 return ast_context()->ReturnInstruction(result, expr->id()); | 8665 return ast_context()->ReturnInstruction(result, expr->id()); |
8702 } | 8666 } |
8703 } else if (op == Token::IN) { | 8667 } else if (op == Token::IN) { |
8704 HIn* result = new(zone()) HIn(context, left, right); | 8668 HIn* result = new(zone()) HIn(context, left, right); |
8705 result->set_position(expr->position()); | 8669 result->set_position(expr->position()); |
8706 return ast_context()->ReturnInstruction(result, expr->id()); | 8670 return ast_context()->ReturnInstruction(result, expr->id()); |
8707 } else if (type_info.IsNonPrimitive()) { | 8671 } else if (overall_type_info.IsNonPrimitive()) { |
8708 switch (op) { | 8672 switch (op) { |
8709 case Token::EQ: | 8673 case Token::EQ: |
8710 case Token::EQ_STRICT: { | 8674 case Token::EQ_STRICT: { |
8711 // Can we get away with map check and not instance type check? | 8675 // Can we get away with map check and not instance type check? |
8712 Handle<Map> map = oracle()->GetCompareMap(expr); | 8676 Handle<Map> map = oracle()->GetCompareMap(expr); |
8713 if (!map.is_null()) { | 8677 if (!map.is_null()) { |
8714 AddCheckMapsWithTransitions(left, map); | 8678 AddCheckMapsWithTransitions(left, map); |
8715 AddCheckMapsWithTransitions(right, map); | 8679 AddCheckMapsWithTransitions(right, map); |
8716 HCompareObjectEqAndBranch* result = | 8680 HCompareObjectEqAndBranch* result = |
8717 new(zone()) HCompareObjectEqAndBranch(left, right); | 8681 new(zone()) HCompareObjectEqAndBranch(left, right); |
8718 result->set_position(expr->position()); | 8682 result->set_position(expr->position()); |
8719 return ast_context()->ReturnControl(result, expr->id()); | 8683 return ast_context()->ReturnControl(result, expr->id()); |
8720 } else { | 8684 } else { |
8721 AddInstruction(new(zone()) HCheckNonSmi(left)); | 8685 AddInstruction(new(zone()) HCheckNonSmi(left)); |
8722 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8686 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
8723 AddInstruction(new(zone()) HCheckNonSmi(right)); | 8687 AddInstruction(new(zone()) HCheckNonSmi(right)); |
8724 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8688 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
8725 HCompareObjectEqAndBranch* result = | 8689 HCompareObjectEqAndBranch* result = |
8726 new(zone()) HCompareObjectEqAndBranch(left, right); | 8690 new(zone()) HCompareObjectEqAndBranch(left, right); |
8727 result->set_position(expr->position()); | 8691 result->set_position(expr->position()); |
8728 return ast_context()->ReturnControl(result, expr->id()); | 8692 return ast_context()->ReturnControl(result, expr->id()); |
8729 } | 8693 } |
8730 } | 8694 } |
8731 default: | 8695 default: |
8732 return Bailout("Unsupported non-primitive compare"); | 8696 return Bailout("Unsupported non-primitive compare"); |
8733 } | 8697 } |
8734 } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && | 8698 } else if (overall_type_info.IsSymbol() && Token::IsEqualityOp(op)) { |
8735 (op == Token::EQ || op == Token::EQ_STRICT)) { | |
8736 AddInstruction(new(zone()) HCheckNonSmi(left)); | 8699 AddInstruction(new(zone()) HCheckNonSmi(left)); |
8737 AddInstruction(HCheckInstanceType::NewIsSymbol(left, zone())); | 8700 AddInstruction(HCheckInstanceType::NewIsSymbol(left, zone())); |
8738 AddInstruction(new(zone()) HCheckNonSmi(right)); | 8701 AddInstruction(new(zone()) HCheckNonSmi(right)); |
8739 AddInstruction(HCheckInstanceType::NewIsSymbol(right, zone())); | 8702 AddInstruction(HCheckInstanceType::NewIsSymbol(right, zone())); |
8740 HCompareObjectEqAndBranch* result = | 8703 HCompareObjectEqAndBranch* result = |
8741 new(zone()) HCompareObjectEqAndBranch(left, right); | 8704 new(zone()) HCompareObjectEqAndBranch(left, right); |
8742 result->set_position(expr->position()); | 8705 result->set_position(expr->position()); |
8743 return ast_context()->ReturnControl(result, expr->id()); | 8706 return ast_context()->ReturnControl(result, expr->id()); |
8744 } else { | 8707 } else { |
8745 Representation r = ToRepresentation(type_info); | 8708 if (combined_rep.IsTagged() || combined_rep.IsNone()) { |
8746 if (r.IsTagged()) { | |
8747 HCompareGeneric* result = | 8709 HCompareGeneric* result = |
8748 new(zone()) HCompareGeneric(context, left, right, op); | 8710 new(zone()) HCompareGeneric(context, left, right, op); |
| 8711 result->set_observed_input_representation(left_rep, right_rep); |
8749 result->set_position(expr->position()); | 8712 result->set_position(expr->position()); |
8750 return ast_context()->ReturnInstruction(result, expr->id()); | 8713 return ast_context()->ReturnInstruction(result, expr->id()); |
8751 } else { | 8714 } else { |
8752 HCompareIDAndBranch* result = | 8715 HCompareIDAndBranch* result = |
8753 new(zone()) HCompareIDAndBranch(left, right, op); | 8716 new(zone()) HCompareIDAndBranch(left, right, op); |
| 8717 result->set_observed_input_representation(left_rep, right_rep); |
8754 result->set_position(expr->position()); | 8718 result->set_position(expr->position()); |
8755 result->SetInputRepresentation(r); | |
8756 return ast_context()->ReturnControl(result, expr->id()); | 8719 return ast_context()->ReturnControl(result, expr->id()); |
8757 } | 8720 } |
8758 } | 8721 } |
8759 } | 8722 } |
8760 | 8723 |
8761 | 8724 |
8762 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8725 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
8763 HValue* value, | 8726 HValue* value, |
8764 NilValue nil) { | 8727 NilValue nil) { |
8765 ASSERT(!HasStackOverflow()); | 8728 ASSERT(!HasStackOverflow()); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8832 environment()->Bind(variable, value); | 8795 environment()->Bind(variable, value); |
8833 } | 8796 } |
8834 break; | 8797 break; |
8835 case Variable::CONTEXT: | 8798 case Variable::CONTEXT: |
8836 if (hole_init) { | 8799 if (hole_init) { |
8837 HValue* value = graph()->GetConstantHole(); | 8800 HValue* value = graph()->GetConstantHole(); |
8838 HValue* context = environment()->LookupContext(); | 8801 HValue* context = environment()->LookupContext(); |
8839 HStoreContextSlot* store = new(zone()) HStoreContextSlot( | 8802 HStoreContextSlot* store = new(zone()) HStoreContextSlot( |
8840 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8803 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8841 AddInstruction(store); | 8804 AddInstruction(store); |
8842 if (store->HasObservableSideEffects()) AddSimulate(proxy->id()); | 8805 if (store->HasObservableSideEffects()) { |
| 8806 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
| 8807 } |
8843 } | 8808 } |
8844 break; | 8809 break; |
8845 case Variable::LOOKUP: | 8810 case Variable::LOOKUP: |
8846 return Bailout("unsupported lookup slot in declaration"); | 8811 return Bailout("unsupported lookup slot in declaration"); |
8847 } | 8812 } |
8848 } | 8813 } |
8849 | 8814 |
8850 | 8815 |
8851 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) { | 8816 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) { |
8852 VariableProxy* proxy = declaration->proxy(); | 8817 VariableProxy* proxy = declaration->proxy(); |
(...skipping 15 matching lines...) Expand all Loading... |
8868 environment()->Bind(variable, value); | 8833 environment()->Bind(variable, value); |
8869 break; | 8834 break; |
8870 } | 8835 } |
8871 case Variable::CONTEXT: { | 8836 case Variable::CONTEXT: { |
8872 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8837 CHECK_ALIVE(VisitForValue(declaration->fun())); |
8873 HValue* value = Pop(); | 8838 HValue* value = Pop(); |
8874 HValue* context = environment()->LookupContext(); | 8839 HValue* context = environment()->LookupContext(); |
8875 HStoreContextSlot* store = new(zone()) HStoreContextSlot( | 8840 HStoreContextSlot* store = new(zone()) HStoreContextSlot( |
8876 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8841 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8877 AddInstruction(store); | 8842 AddInstruction(store); |
8878 if (store->HasObservableSideEffects()) AddSimulate(proxy->id()); | 8843 if (store->HasObservableSideEffects()) { |
| 8844 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); |
| 8845 } |
8879 break; | 8846 break; |
8880 } | 8847 } |
8881 case Variable::LOOKUP: | 8848 case Variable::LOOKUP: |
8882 return Bailout("unsupported lookup slot in declaration"); | 8849 return Bailout("unsupported lookup slot in declaration"); |
8883 } | 8850 } |
8884 } | 8851 } |
8885 | 8852 |
8886 | 8853 |
8887 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 8854 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
8888 UNREACHABLE(); | 8855 UNREACHABLE(); |
(...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10011 } | 9978 } |
10012 } | 9979 } |
10013 | 9980 |
10014 #ifdef DEBUG | 9981 #ifdef DEBUG |
10015 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9982 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10016 if (allocator_ != NULL) allocator_->Verify(); | 9983 if (allocator_ != NULL) allocator_->Verify(); |
10017 #endif | 9984 #endif |
10018 } | 9985 } |
10019 | 9986 |
10020 } } // namespace v8::internal | 9987 } } // namespace v8::internal |
OLD | NEW |