Chromium Code Reviews| 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, bool optional) { |
| 137 ASSERT(HasEnvironment()); | 137 ASSERT(HasEnvironment()); |
| 138 HEnvironment* environment = last_environment(); | 138 HEnvironment* environment = last_environment(); |
| 139 ASSERT(ast_id.IsNone() || | 139 ASSERT(ast_id.IsNone() || |
| 140 environment->closure()->shared()->VerifyBailoutId(ast_id)); | 140 environment->closure()->shared()->VerifyBailoutId(ast_id)); |
| 141 | 141 |
| 142 int push_count = environment->push_count(); | 142 int push_count = environment->push_count(); |
| 143 int pop_count = environment->pop_count(); | 143 int pop_count = environment->pop_count(); |
| 144 | 144 |
| 145 HSimulate* instr = new(zone()) HSimulate(ast_id, pop_count, zone()); | 145 HSimulate* instr = new(zone()) HSimulate(ast_id, pop_count, zone(), optional); |
| 146 for (int i = push_count - 1; i >= 0; --i) { | 146 // Order of pushed values: newest (top of stack) first. This allows |
| 147 // HSimulate::MergeInto() to easily append additional pushed values | |
| 148 // that are older (from further down the stack). | |
| 149 for (int i = 0; i < push_count; ++i) { | |
| 147 instr->AddPushedValue(environment->ExpressionStackAt(i)); | 150 instr->AddPushedValue(environment->ExpressionStackAt(i)); |
| 148 } | 151 } |
| 149 for (int i = 0; i < environment->assigned_variables()->length(); ++i) { | 152 for (int i = 0; i < environment->assigned_variables()->length(); ++i) { |
| 150 int index = environment->assigned_variables()->at(i); | 153 int index = environment->assigned_variables()->at(i); |
| 151 instr->AddAssignedValue(index, environment->Lookup(index)); | 154 instr->AddAssignedValue(index, environment->Lookup(index)); |
| 152 } | 155 } |
| 153 environment->ClearHistory(); | 156 environment->ClearHistory(); |
| 154 return instr; | 157 return instr; |
| 155 } | 158 } |
| 156 | 159 |
| (...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1284 Analyze(block->dominated_blocks()->at(i)); | 1287 Analyze(block->dominated_blocks()->at(i)); |
| 1285 } | 1288 } |
| 1286 | 1289 |
| 1287 RollBackTo(last_changed_range); | 1290 RollBackTo(last_changed_range); |
| 1288 } | 1291 } |
| 1289 | 1292 |
| 1290 | 1293 |
| 1291 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, | 1294 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, |
| 1292 HBasicBlock* dest) { | 1295 HBasicBlock* dest) { |
| 1293 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); | 1296 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); |
| 1294 if (test->GetInputRepresentation().IsInteger32()) { | 1297 if (test->representation().IsInteger32()) { |
| 1295 Token::Value op = test->token(); | 1298 Token::Value op = test->token(); |
| 1296 if (test->SecondSuccessor() == dest) { | 1299 if (test->SecondSuccessor() == dest) { |
| 1297 op = Token::NegateCompareOp(op); | 1300 op = Token::NegateCompareOp(op); |
| 1298 } | 1301 } |
| 1299 Token::Value inverted_op = Token::InvertCompareOp(op); | 1302 Token::Value inverted_op = Token::InvertCompareOp(op); |
| 1300 UpdateControlFlowRange(op, test->left(), test->right()); | 1303 UpdateControlFlowRange(op, test->left(), test->right()); |
| 1301 UpdateControlFlowRange(inverted_op, test->right(), test->left()); | 1304 UpdateControlFlowRange(inverted_op, test->right(), test->left()); |
| 1302 } | 1305 } |
| 1303 } | 1306 } |
| 1304 | 1307 |
| (...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2232 dominated); | 2235 dominated); |
| 2233 successor_map->Kill(side_effects_on_all_paths); | 2236 successor_map->Kill(side_effects_on_all_paths); |
| 2234 successor_dominators->Kill(side_effects_on_all_paths); | 2237 successor_dominators->Kill(side_effects_on_all_paths); |
| 2235 } | 2238 } |
| 2236 } | 2239 } |
| 2237 current = next; | 2240 current = next; |
| 2238 } | 2241 } |
| 2239 } | 2242 } |
| 2240 | 2243 |
| 2241 | 2244 |
| 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) { | 2245 void HInferRepresentation::AddToWorklist(HValue* current) { |
| 2267 if (current->representation().IsSpecialization()) return; | 2246 if (current->representation().IsTagged()) return; |
| 2268 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; | 2247 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; |
| 2269 if (in_worklist_.Contains(current->id())) return; | 2248 if (in_worklist_.Contains(current->id())) return; |
| 2270 worklist_.Add(current, zone()); | 2249 worklist_.Add(current, zone()); |
| 2271 in_worklist_.Add(current->id()); | 2250 in_worklist_.Add(current->id()); |
| 2272 } | 2251 } |
| 2273 | 2252 |
| 2274 | 2253 |
| 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() { | 2254 void HInferRepresentation::Analyze() { |
| 2375 HPhase phase("H_Infer representations", graph_); | 2255 HPhase phase("H_Infer representations", graph_); |
| 2376 | 2256 |
| 2377 // (1) Initialize bit vectors and count real uses. Each phi gets a | 2257 // (1) Initialize bit vectors and count real uses. Each phi gets a |
| 2378 // bit-vector of length <number of phis>. | 2258 // bit-vector of length <number of phis>. |
| 2379 const ZoneList<HPhi*>* phi_list = graph_->phi_list(); | 2259 const ZoneList<HPhi*>* phi_list = graph_->phi_list(); |
| 2380 int phi_count = phi_list->length(); | 2260 int phi_count = phi_list->length(); |
| 2381 ZoneList<BitVector*> connected_phis(phi_count, graph_->zone()); | 2261 ZoneList<BitVector*> connected_phis(phi_count, graph_->zone()); |
| 2382 for (int i = 0; i < phi_count; ++i) { | 2262 for (int i = 0; i < phi_count; ++i) { |
| 2383 phi_list->at(i)->InitRealUses(i); | 2263 phi_list->at(i)->InitRealUses(i); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 2414 for (int i = 0; i < phi_count; ++i) { | 2294 for (int i = 0; i < phi_count; ++i) { |
| 2415 HPhi* phi = phi_list->at(i); | 2295 HPhi* phi = phi_list->at(i); |
| 2416 bool cti = phi->AllOperandsConvertibleToInteger(); | 2296 bool cti = phi->AllOperandsConvertibleToInteger(); |
| 2417 if (cti) continue; | 2297 if (cti) continue; |
| 2418 | 2298 |
| 2419 for (BitVector::Iterator it(connected_phis.at(i)); | 2299 for (BitVector::Iterator it(connected_phis.at(i)); |
| 2420 !it.Done(); | 2300 !it.Done(); |
| 2421 it.Advance()) { | 2301 it.Advance()) { |
| 2422 HPhi* phi = phi_list->at(it.Current()); | 2302 HPhi* phi = phi_list->at(it.Current()); |
| 2423 phi->set_is_convertible_to_integer(false); | 2303 phi->set_is_convertible_to_integer(false); |
| 2424 phi->ResetInteger32Uses(); | |
| 2425 } | 2304 } |
| 2426 } | 2305 } |
| 2427 | 2306 |
| 2428 // (3b) Use the phi reachability information from step 2 to | 2307 // (3b) Use the phi reachability information from step 2 to |
| 2429 // sum up the non-phi use counts of all connected phis. | 2308 // sum up the non-phi use counts of all connected phis. |
| 2430 for (int i = 0; i < phi_count; ++i) { | 2309 for (int i = 0; i < phi_count; ++i) { |
| 2431 HPhi* phi = phi_list->at(i); | 2310 HPhi* phi = phi_list->at(i); |
| 2432 for (BitVector::Iterator it(connected_phis.at(i)); | 2311 for (BitVector::Iterator it(connected_phis.at(i)); |
| 2433 !it.Done(); | 2312 !it.Done(); |
| 2434 it.Advance()) { | 2313 it.Advance()) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2450 while (current != NULL) { | 2329 while (current != NULL) { |
| 2451 AddToWorklist(current); | 2330 AddToWorklist(current); |
| 2452 current = current->next(); | 2331 current = current->next(); |
| 2453 } | 2332 } |
| 2454 } | 2333 } |
| 2455 | 2334 |
| 2456 // Do a fixed point iteration, trying to improve representations | 2335 // Do a fixed point iteration, trying to improve representations |
| 2457 while (!worklist_.is_empty()) { | 2336 while (!worklist_.is_empty()) { |
| 2458 HValue* current = worklist_.RemoveLast(); | 2337 HValue* current = worklist_.RemoveLast(); |
| 2459 in_worklist_.Remove(current->id()); | 2338 in_worklist_.Remove(current->id()); |
| 2460 InferBasedOnInputs(current); | 2339 current->InferRepresentation(this); |
| 2461 InferBasedOnUses(current); | 2340 } |
| 2341 | |
| 2342 // Lastly: any instruction that we don't have representation information | |
| 2343 // for defaults to Tagged. | |
| 2344 for (int i = 0; i < graph_->blocks()->length(); ++i) { | |
| 2345 HBasicBlock* block = graph_->blocks()->at(i); | |
| 2346 const ZoneList<HPhi*>* phis = block->phis(); | |
| 2347 for (int j = 0; j < phis->length(); ++j) { | |
| 2348 HPhi* phi = phis->at(j); | |
| 2349 if (phi->representation().IsNone()) { | |
| 2350 phi->ChangeRepresentation(Representation::Tagged()); | |
| 2351 } | |
| 2352 } | |
| 2353 for (HInstruction* current = block->first(); | |
| 2354 current != NULL; current = current->next()) { | |
| 2355 if (current->representation().IsNone() && | |
| 2356 current->CheckFlag(HInstruction::kFlexibleRepresentation)) { | |
| 2357 current->ChangeRepresentation(Representation::Tagged()); | |
| 2358 } | |
| 2359 } | |
| 2360 } | |
| 2361 | |
| 2362 // With representations figured out, we can now remove HSimulates | |
|
danno
2012/11/06 11:42:59
Make this a new method
Jakob Kummerow
2012/11/06 12:44:05
Done.
| |
| 2363 // that are not needed after all by folding them into the following | |
| 2364 // HSimulate. | |
| 2365 for (int i = 0; i < graph_->blocks()->length(); ++i) { | |
| 2366 HBasicBlock* block = graph_->blocks()->at(i); | |
| 2367 // Always reset the folding candidate at the start of a block. | |
| 2368 HSimulate* folding_candidate = NULL; | |
| 2369 // Nasty heuristic: Never remove the first simulate in a block. This | |
| 2370 // just so happens to have a beneficial effect on register allocation. | |
| 2371 bool first = true; | |
| 2372 for (HInstruction* current = block->first(); | |
| 2373 current != NULL; current = current->next()) { | |
| 2374 if (current->IsLeaveInlined()) { | |
| 2375 // Never fold simulates from inlined environments into simulates | |
| 2376 // in the outer environment. | |
| 2377 // (Before each HEnterInlined, there is a non-foldable HSimulate | |
| 2378 // anyway, so we get the barrier in the other direction for free.) | |
| 2379 if (folding_candidate != NULL) { | |
| 2380 folding_candidate->DeleteAndReplaceWith(NULL); | |
| 2381 } | |
| 2382 folding_candidate = NULL; | |
| 2383 continue; | |
| 2384 } | |
| 2385 // If we have an HSimulate and a candidate, perform the folding. | |
| 2386 if (!current->IsSimulate()) continue; | |
| 2387 if (first) { | |
| 2388 first = false; | |
| 2389 continue; | |
| 2390 } | |
| 2391 HSimulate* current_simulate = HSimulate::cast(current); | |
| 2392 if (folding_candidate != NULL) { | |
| 2393 folding_candidate->MergeInto(current_simulate); | |
| 2394 folding_candidate->DeleteAndReplaceWith(NULL); | |
| 2395 folding_candidate = NULL; | |
| 2396 } | |
| 2397 // Check if the current simulate is a candidate for folding. | |
| 2398 if (current_simulate->previous()->HasObservableSideEffects() && | |
| 2399 !current_simulate->next()->IsSimulate()) { | |
| 2400 continue; | |
| 2401 } | |
| 2402 if (!current_simulate->is_candidate_for_removal()) { | |
| 2403 continue; | |
| 2404 } | |
| 2405 folding_candidate = current_simulate; | |
| 2406 } | |
| 2462 } | 2407 } |
| 2463 } | 2408 } |
| 2464 | 2409 |
| 2465 | 2410 |
| 2466 void HGraph::InitializeInferredTypes() { | 2411 void HGraph::InitializeInferredTypes() { |
| 2467 HPhase phase("H_Inferring types", this); | 2412 HPhase phase("H_Inferring types", this); |
| 2468 InitializeInferredTypes(0, this->blocks_.length() - 1); | 2413 InitializeInferredTypes(0, this->blocks_.length() - 1); |
| 2469 } | 2414 } |
| 2470 | 2415 |
| 2471 | 2416 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2546 int use_index, | 2491 int use_index, |
| 2547 Representation to) { | 2492 Representation to) { |
| 2548 // Insert the representation change right before its use. For phi-uses we | 2493 // Insert the representation change right before its use. For phi-uses we |
| 2549 // insert at the end of the corresponding predecessor. | 2494 // insert at the end of the corresponding predecessor. |
| 2550 HInstruction* next = NULL; | 2495 HInstruction* next = NULL; |
| 2551 if (use_value->IsPhi()) { | 2496 if (use_value->IsPhi()) { |
| 2552 next = use_value->block()->predecessors()->at(use_index)->end(); | 2497 next = use_value->block()->predecessors()->at(use_index)->end(); |
| 2553 } else { | 2498 } else { |
| 2554 next = HInstruction::cast(use_value); | 2499 next = HInstruction::cast(use_value); |
| 2555 } | 2500 } |
| 2556 | |
| 2557 // For constants we try to make the representation change at compile | 2501 // For constants we try to make the representation change at compile |
| 2558 // time. When a representation change is not possible without loss of | 2502 // time. When a representation change is not possible without loss of |
| 2559 // information we treat constants like normal instructions and insert the | 2503 // information we treat constants like normal instructions and insert the |
| 2560 // change instructions for them. | 2504 // change instructions for them. |
| 2561 HInstruction* new_value = NULL; | 2505 HInstruction* new_value = NULL; |
| 2562 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); | 2506 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); |
| 2563 bool deoptimize_on_undefined = | 2507 bool deoptimize_on_undefined = |
| 2564 use_value->CheckFlag(HValue::kDeoptimizeOnUndefined); | 2508 use_value->CheckFlag(HValue::kDeoptimizeOnUndefined); |
| 2565 if (value->IsConstant()) { | 2509 if (value->IsConstant()) { |
| 2566 HConstant* constant = HConstant::cast(value); | 2510 HConstant* constant = HConstant::cast(value); |
| 2567 // Try to create a new copy of the constant with the new representation. | 2511 // Try to create a new copy of the constant with the new representation. |
| 2568 new_value = is_truncating | 2512 new_value = (is_truncating && to.IsInteger32()) |
| 2569 ? constant->CopyToTruncatedInt32(zone()) | 2513 ? constant->CopyToTruncatedInt32(zone()) |
| 2570 : constant->CopyToRepresentation(to, zone()); | 2514 : constant->CopyToRepresentation(to, zone()); |
| 2571 } | 2515 } |
| 2572 | 2516 |
| 2573 if (new_value == NULL) { | 2517 if (new_value == NULL) { |
| 2574 new_value = new(zone()) HChange(value, to, | 2518 new_value = new(zone()) HChange(value, to, |
| 2575 is_truncating, deoptimize_on_undefined); | 2519 is_truncating, deoptimize_on_undefined); |
| 2576 } | 2520 } |
| 2577 | 2521 |
| 2578 new_value->InsertBefore(next); | 2522 new_value->InsertBefore(next); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2618 if (phi->representation().IsInteger32()) { | 2562 if (phi->representation().IsInteger32()) { |
| 2619 phi->SetFlag(HValue::kTruncatingToInt32); | 2563 phi->SetFlag(HValue::kTruncatingToInt32); |
| 2620 } | 2564 } |
| 2621 } | 2565 } |
| 2622 bool change = true; | 2566 bool change = true; |
| 2623 while (change) { | 2567 while (change) { |
| 2624 change = false; | 2568 change = false; |
| 2625 for (int i = 0; i < phi_list()->length(); i++) { | 2569 for (int i = 0; i < phi_list()->length(); i++) { |
| 2626 HPhi* phi = phi_list()->at(i); | 2570 HPhi* phi = phi_list()->at(i); |
| 2627 if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; | 2571 if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; |
| 2628 if (!phi->CheckUsesForFlag(HValue::kTruncatingToInt32)) { | 2572 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
| 2629 phi->ClearFlag(HValue::kTruncatingToInt32); | 2573 HValue* use = it.value(); |
| 2630 change = true; | 2574 Representation input_representation = |
|
danno
2012/11/06 11:42:59
Comment would be nice.
Jakob Kummerow
2012/11/06 12:44:05
Done.
| |
| 2575 use->RequiredInputRepresentation(it.index()); | |
| 2576 if ((input_representation.IsInteger32() && | |
| 2577 !use->CheckFlag(HValue::kTruncatingToInt32)) || | |
| 2578 input_representation.IsDouble()) { | |
| 2579 if (FLAG_trace_representation) { | |
| 2580 PrintF("#%d Phi is not truncating because of #%d %s\n", | |
| 2581 phi->id(), it.value()->id(), it.value()->Mnemonic()); | |
| 2582 } | |
| 2583 phi->ClearFlag(HValue::kTruncatingToInt32); | |
| 2584 change = true; | |
| 2585 break; | |
| 2586 } | |
| 2631 } | 2587 } |
| 2632 } | 2588 } |
| 2633 } | 2589 } |
| 2634 | 2590 |
| 2635 for (int i = 0; i < blocks_.length(); ++i) { | 2591 for (int i = 0; i < blocks_.length(); ++i) { |
| 2636 // Process phi instructions first. | 2592 // Process phi instructions first. |
| 2637 const ZoneList<HPhi*>* phis = blocks_[i]->phis(); | 2593 const ZoneList<HPhi*>* phis = blocks_[i]->phis(); |
| 2638 for (int j = 0; j < phis->length(); j++) { | 2594 for (int j = 0; j < phis->length(); j++) { |
| 2639 InsertRepresentationChangesForValue(phis->at(j)); | 2595 InsertRepresentationChangesForValue(phis->at(j)); |
| 2640 } | 2596 } |
| 2641 | 2597 |
| 2642 // Process normal instructions. | 2598 // Process normal instructions. |
| 2643 HInstruction* current = blocks_[i]->first(); | 2599 HInstruction* current = blocks_[i]->first(); |
| 2644 while (current != NULL) { | 2600 while (current != NULL) { |
| 2601 HInstruction* next = current->next(); | |
| 2645 InsertRepresentationChangesForValue(current); | 2602 InsertRepresentationChangesForValue(current); |
| 2646 current = current->next(); | 2603 current = next; |
| 2647 } | 2604 } |
| 2648 } | 2605 } |
| 2649 } | 2606 } |
| 2650 | 2607 |
| 2651 | 2608 |
| 2652 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { | 2609 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { |
| 2653 if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return; | 2610 if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return; |
| 2654 phi->SetFlag(HValue::kDeoptimizeOnUndefined); | 2611 phi->SetFlag(HValue::kDeoptimizeOnUndefined); |
| 2655 for (int i = 0; i < phi->OperandCount(); ++i) { | 2612 for (int i = 0; i < phi->OperandCount(); ++i) { |
| 2656 HValue* input = phi->OperandAt(i); | 2613 HValue* input = phi->OperandAt(i); |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3031 | 2988 |
| 3032 | 2989 |
| 3033 void TestContext::ReturnValue(HValue* value) { | 2990 void TestContext::ReturnValue(HValue* value) { |
| 3034 BuildBranch(value); | 2991 BuildBranch(value); |
| 3035 } | 2992 } |
| 3036 | 2993 |
| 3037 | 2994 |
| 3038 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 2995 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 3039 ASSERT(!instr->IsControlInstruction()); | 2996 ASSERT(!instr->IsControlInstruction()); |
| 3040 owner()->AddInstruction(instr); | 2997 owner()->AddInstruction(instr); |
| 3041 if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); | 2998 if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id, true); |
|
danno
2012/11/06 11:42:59
Create an enum for this
Jakob Kummerow
2012/11/06 12:44:05
Done.
| |
| 3042 } | 2999 } |
| 3043 | 3000 |
| 3044 | 3001 |
| 3045 void EffectContext::ReturnControl(HControlInstruction* instr, | 3002 void EffectContext::ReturnControl(HControlInstruction* instr, |
| 3046 BailoutId ast_id) { | 3003 BailoutId ast_id) { |
| 3047 ASSERT(!instr->HasObservableSideEffects()); | 3004 ASSERT(!instr->HasObservableSideEffects()); |
| 3048 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 3005 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| 3049 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 3006 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| 3050 instr->SetSuccessorAt(0, empty_true); | 3007 instr->SetSuccessorAt(0, empty_true); |
| 3051 instr->SetSuccessorAt(1, empty_false); | 3008 instr->SetSuccessorAt(1, empty_false); |
| 3052 owner()->current_block()->Finish(instr); | 3009 owner()->current_block()->Finish(instr); |
| 3053 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); | 3010 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); |
| 3054 owner()->set_current_block(join); | 3011 owner()->set_current_block(join); |
| 3055 } | 3012 } |
| 3056 | 3013 |
| 3057 | 3014 |
| 3058 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 3015 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 3059 ASSERT(!instr->IsControlInstruction()); | 3016 ASSERT(!instr->IsControlInstruction()); |
| 3060 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 3017 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
| 3061 return owner()->Bailout("bad value context for arguments object value"); | 3018 return owner()->Bailout("bad value context for arguments object value"); |
| 3062 } | 3019 } |
| 3063 owner()->AddInstruction(instr); | 3020 owner()->AddInstruction(instr); |
| 3064 owner()->Push(instr); | 3021 owner()->Push(instr); |
| 3065 if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); | 3022 if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id, true); |
| 3066 } | 3023 } |
| 3067 | 3024 |
| 3068 | 3025 |
| 3069 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 3026 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
| 3070 ASSERT(!instr->HasObservableSideEffects()); | 3027 ASSERT(!instr->HasObservableSideEffects()); |
| 3071 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 3028 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
| 3072 return owner()->Bailout("bad value context for arguments object value"); | 3029 return owner()->Bailout("bad value context for arguments object value"); |
| 3073 } | 3030 } |
| 3074 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 3031 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
| 3075 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); | 3032 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 3087 | 3044 |
| 3088 | 3045 |
| 3089 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 3046 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
| 3090 ASSERT(!instr->IsControlInstruction()); | 3047 ASSERT(!instr->IsControlInstruction()); |
| 3091 HGraphBuilder* builder = owner(); | 3048 HGraphBuilder* builder = owner(); |
| 3092 builder->AddInstruction(instr); | 3049 builder->AddInstruction(instr); |
| 3093 // We expect a simulate after every expression with side effects, though | 3050 // 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). | 3051 // this one isn't actually needed (and wouldn't work if it were targeted). |
| 3095 if (instr->HasObservableSideEffects()) { | 3052 if (instr->HasObservableSideEffects()) { |
| 3096 builder->Push(instr); | 3053 builder->Push(instr); |
| 3097 builder->AddSimulate(ast_id); | 3054 builder->AddSimulate(ast_id, true); |
| 3098 builder->Pop(); | 3055 builder->Pop(); |
| 3099 } | 3056 } |
| 3100 BuildBranch(instr); | 3057 BuildBranch(instr); |
| 3101 } | 3058 } |
| 3102 | 3059 |
| 3103 | 3060 |
| 3104 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 3061 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
| 3105 ASSERT(!instr->HasObservableSideEffects()); | 3062 ASSERT(!instr->HasObservableSideEffects()); |
| 3106 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 3063 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| 3107 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 3064 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| (...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3803 } | 3760 } |
| 3804 | 3761 |
| 3805 | 3762 |
| 3806 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 3763 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 3807 ASSERT(current_block() != NULL); | 3764 ASSERT(current_block() != NULL); |
| 3808 current_block()->AddInstruction(instr); | 3765 current_block()->AddInstruction(instr); |
| 3809 return instr; | 3766 return instr; |
| 3810 } | 3767 } |
| 3811 | 3768 |
| 3812 | 3769 |
| 3813 void HGraphBuilder::AddSimulate(BailoutId ast_id) { | 3770 void HGraphBuilder::AddSimulate(BailoutId ast_id, bool optional) { |
| 3814 ASSERT(current_block() != NULL); | 3771 ASSERT(current_block() != NULL); |
| 3815 current_block()->AddSimulate(ast_id); | 3772 current_block()->AddSimulate(ast_id, optional); |
| 3816 } | 3773 } |
| 3817 | 3774 |
| 3818 | 3775 |
| 3819 void HGraphBuilder::AddPhi(HPhi* instr) { | 3776 void HGraphBuilder::AddPhi(HPhi* instr) { |
| 3820 ASSERT(current_block() != NULL); | 3777 ASSERT(current_block() != NULL); |
| 3821 current_block()->AddPhi(instr); | 3778 current_block()->AddPhi(instr); |
| 3822 } | 3779 } |
| 3823 | 3780 |
| 3824 | 3781 |
| 3825 void HGraphBuilder::PushAndAdd(HInstruction* instr) { | 3782 void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4162 switch_type = SMI_SWITCH; | 4119 switch_type = SMI_SWITCH; |
| 4163 } else if (clause->label()->IsStringLiteral()) { | 4120 } else if (clause->label()->IsStringLiteral()) { |
| 4164 switch_type = STRING_SWITCH; | 4121 switch_type = STRING_SWITCH; |
| 4165 } else { | 4122 } else { |
| 4166 return Bailout("SwitchStatement: non-literal switch label"); | 4123 return Bailout("SwitchStatement: non-literal switch label"); |
| 4167 } | 4124 } |
| 4168 } else if ((switch_type == STRING_SWITCH && | 4125 } else if ((switch_type == STRING_SWITCH && |
| 4169 !clause->label()->IsStringLiteral()) || | 4126 !clause->label()->IsStringLiteral()) || |
| 4170 (switch_type == SMI_SWITCH && | 4127 (switch_type == SMI_SWITCH && |
| 4171 !clause->label()->IsSmiLiteral())) { | 4128 !clause->label()->IsSmiLiteral())) { |
| 4172 return Bailout("SwitchStatemnt: mixed label types are not supported"); | 4129 return Bailout("SwitchStatement: mixed label types are not supported"); |
| 4173 } | 4130 } |
| 4174 } | 4131 } |
| 4175 | 4132 |
| 4176 HUnaryControlInstruction* string_check = NULL; | 4133 HUnaryControlInstruction* string_check = NULL; |
| 4177 HBasicBlock* not_string_block = NULL; | 4134 HBasicBlock* not_string_block = NULL; |
| 4178 | 4135 |
| 4179 // Test switch's tag value if all clauses are string literals | 4136 // Test switch's tag value if all clauses are string literals |
| 4180 if (switch_type == STRING_SWITCH) { | 4137 if (switch_type == STRING_SWITCH) { |
| 4181 string_check = new(zone()) HIsStringAndBranch(tag_value); | 4138 string_check = new(zone()) HIsStringAndBranch(tag_value); |
| 4182 first_test_block = graph()->CreateBasicBlock(); | 4139 first_test_block = graph()->CreateBasicBlock(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4216 // account for invisible uses. | 4173 // account for invisible uses. |
| 4217 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | 4174 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); |
| 4218 set_current_block(NULL); | 4175 set_current_block(NULL); |
| 4219 break; | 4176 break; |
| 4220 } | 4177 } |
| 4221 | 4178 |
| 4222 HCompareIDAndBranch* compare_ = | 4179 HCompareIDAndBranch* compare_ = |
| 4223 new(zone()) HCompareIDAndBranch(tag_value, | 4180 new(zone()) HCompareIDAndBranch(tag_value, |
| 4224 label_value, | 4181 label_value, |
| 4225 Token::EQ_STRICT); | 4182 Token::EQ_STRICT); |
| 4226 compare_->SetInputRepresentation(Representation::Integer32()); | 4183 compare_->set_observed_input_representation( |
| 4184 Representation::Integer32(), Representation::Integer32()); | |
| 4227 compare = compare_; | 4185 compare = compare_; |
| 4228 } else { | 4186 } else { |
| 4229 compare = new(zone()) HStringCompareAndBranch(context, tag_value, | 4187 compare = new(zone()) HStringCompareAndBranch(context, tag_value, |
| 4230 label_value, | 4188 label_value, |
| 4231 Token::EQ_STRICT); | 4189 Token::EQ_STRICT); |
| 4232 } | 4190 } |
| 4233 | 4191 |
| 4234 compare->SetSuccessorAt(0, body_block); | 4192 compare->SetSuccessorAt(0, body_block); |
| 4235 compare->SetSuccessorAt(1, next_test_block); | 4193 compare->SetSuccessorAt(1, next_test_block); |
| 4236 current_block()->Finish(compare); | 4194 current_block()->Finish(compare); |
| 4237 | 4195 |
| 4238 set_current_block(next_test_block); | 4196 set_current_block(next_test_block); |
| 4239 } | 4197 } |
| 4240 | 4198 |
| 4241 // Save the current block to use for the default or to join with the | 4199 // 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); | 4538 current_block()->Goto(loop_entry); |
| 4581 set_current_block(loop_entry); | 4539 set_current_block(loop_entry); |
| 4582 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 4540 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
| 4583 | 4541 |
| 4584 HValue* index = environment()->ExpressionStackAt(0); | 4542 HValue* index = environment()->ExpressionStackAt(0); |
| 4585 HValue* limit = environment()->ExpressionStackAt(1); | 4543 HValue* limit = environment()->ExpressionStackAt(1); |
| 4586 | 4544 |
| 4587 // Check that we still have more keys. | 4545 // Check that we still have more keys. |
| 4588 HCompareIDAndBranch* compare_index = | 4546 HCompareIDAndBranch* compare_index = |
| 4589 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); | 4547 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); |
| 4590 compare_index->SetInputRepresentation(Representation::Integer32()); | 4548 compare_index->set_observed_input_representation( |
| 4549 Representation::Integer32(), Representation::Integer32()); | |
| 4591 | 4550 |
| 4592 HBasicBlock* loop_body = graph()->CreateBasicBlock(); | 4551 HBasicBlock* loop_body = graph()->CreateBasicBlock(); |
| 4593 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); | 4552 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); |
| 4594 | 4553 |
| 4595 compare_index->SetSuccessorAt(0, loop_body); | 4554 compare_index->SetSuccessorAt(0, loop_body); |
| 4596 compare_index->SetSuccessorAt(1, loop_successor); | 4555 compare_index->SetSuccessorAt(1, loop_successor); |
| 4597 current_block()->Finish(compare_index); | 4556 current_block()->Finish(compare_index); |
| 4598 | 4557 |
| 4599 set_current_block(loop_successor); | 4558 set_current_block(loop_successor); |
| 4600 Drop(5); | 4559 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"); | 4814 return Bailout("reference to a variable which requires dynamic lookup"); |
| 4856 } | 4815 } |
| 4857 } | 4816 } |
| 4858 | 4817 |
| 4859 | 4818 |
| 4860 void HGraphBuilder::VisitLiteral(Literal* expr) { | 4819 void HGraphBuilder::VisitLiteral(Literal* expr) { |
| 4861 ASSERT(!HasStackOverflow()); | 4820 ASSERT(!HasStackOverflow()); |
| 4862 ASSERT(current_block() != NULL); | 4821 ASSERT(current_block() != NULL); |
| 4863 ASSERT(current_block()->HasPredecessor()); | 4822 ASSERT(current_block()->HasPredecessor()); |
| 4864 HConstant* instr = | 4823 HConstant* instr = |
| 4865 new(zone()) HConstant(expr->handle(), Representation::Tagged()); | 4824 new(zone()) HConstant(expr->handle(), Representation::None()); |
| 4866 return ast_context()->ReturnInstruction(instr, expr->id()); | 4825 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4867 } | 4826 } |
| 4868 | 4827 |
| 4869 | 4828 |
| 4870 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 4829 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 4871 ASSERT(!HasStackOverflow()); | 4830 ASSERT(!HasStackOverflow()); |
| 4872 ASSERT(current_block() != NULL); | 4831 ASSERT(current_block() != NULL); |
| 4873 ASSERT(current_block()->HasPredecessor()); | 4832 ASSERT(current_block()->HasPredecessor()); |
| 4874 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4833 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 4875 Handle<FixedArray> literals(closure->literals()); | 4834 Handle<FixedArray> literals(closure->literals()); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5092 Handle<JSFunction> setter; | 5051 Handle<JSFunction> setter; |
| 5093 Handle<JSObject> holder; | 5052 Handle<JSObject> holder; |
| 5094 ASSERT(!LookupSetter(map, name, &setter, &holder)); | 5053 ASSERT(!LookupSetter(map, name, &setter, &holder)); |
| 5095 #endif | 5054 #endif |
| 5096 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, | 5055 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, |
| 5097 name, | 5056 name, |
| 5098 value, | 5057 value, |
| 5099 map)); | 5058 map)); |
| 5100 } | 5059 } |
| 5101 AddInstruction(store); | 5060 AddInstruction(store); |
| 5102 if (store->HasObservableSideEffects()) AddSimulate(key->id()); | 5061 if (store->HasObservableSideEffects()) AddSimulate(key->id(), true); |
| 5103 } else { | 5062 } else { |
| 5104 CHECK_ALIVE(VisitForEffect(value)); | 5063 CHECK_ALIVE(VisitForEffect(value)); |
| 5105 } | 5064 } |
| 5106 break; | 5065 break; |
| 5107 } | 5066 } |
| 5108 // Fall through. | 5067 // Fall through. |
| 5109 case ObjectLiteral::Property::PROTOTYPE: | 5068 case ObjectLiteral::Property::PROTOTYPE: |
| 5110 case ObjectLiteral::Property::SETTER: | 5069 case ObjectLiteral::Property::SETTER: |
| 5111 case ObjectLiteral::Property::GETTER: | 5070 case ObjectLiteral::Property::GETTER: |
| 5112 return Bailout("Object literal with complex property"); | 5071 return Bailout("Object literal with complex property"); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5473 | 5432 |
| 5474 if (join != NULL) { | 5433 if (join != NULL) { |
| 5475 if (!ast_context()->IsEffect()) Push(value); | 5434 if (!ast_context()->IsEffect()) Push(value); |
| 5476 current_block()->Goto(join); | 5435 current_block()->Goto(join); |
| 5477 } else { | 5436 } else { |
| 5478 // The HSimulate for the store should not see the stored value in | 5437 // The HSimulate for the store should not see the stored value in |
| 5479 // effect contexts (it is not materialized at expr->id() in the | 5438 // effect contexts (it is not materialized at expr->id() in the |
| 5480 // unoptimized code). | 5439 // unoptimized code). |
| 5481 if (instr->HasObservableSideEffects()) { | 5440 if (instr->HasObservableSideEffects()) { |
| 5482 if (ast_context()->IsEffect()) { | 5441 if (ast_context()->IsEffect()) { |
| 5483 AddSimulate(expr->id()); | 5442 AddSimulate(expr->id(), true); |
| 5484 } else { | 5443 } else { |
| 5485 Push(value); | 5444 Push(value); |
| 5486 AddSimulate(expr->id()); | 5445 AddSimulate(expr->id(), true); |
| 5487 Drop(1); | 5446 Drop(1); |
| 5488 } | 5447 } |
| 5489 } | 5448 } |
| 5490 return ast_context()->ReturnValue(value); | 5449 return ast_context()->ReturnValue(value); |
| 5491 } | 5450 } |
| 5492 } | 5451 } |
| 5493 | 5452 |
| 5494 ASSERT(join != NULL); | 5453 ASSERT(join != NULL); |
| 5495 join->SetJoinId(expr->id()); | 5454 join->SetJoinId(expr->id()); |
| 5496 set_current_block(join); | 5455 set_current_block(join); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5546 Drop(2); | 5505 Drop(2); |
| 5547 return HandlePolymorphicStoreNamedField(expr, object, value, types, name); | 5506 return HandlePolymorphicStoreNamedField(expr, object, value, types, name); |
| 5548 } else { | 5507 } else { |
| 5549 Drop(2); | 5508 Drop(2); |
| 5550 instr = BuildStoreNamedGeneric(object, name, value); | 5509 instr = BuildStoreNamedGeneric(object, name, value); |
| 5551 } | 5510 } |
| 5552 | 5511 |
| 5553 Push(value); | 5512 Push(value); |
| 5554 instr->set_position(expr->position()); | 5513 instr->set_position(expr->position()); |
| 5555 AddInstruction(instr); | 5514 AddInstruction(instr); |
| 5556 if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 5515 if (instr->HasObservableSideEffects()) { |
| 5516 AddSimulate(expr->AssignmentId(), true); | |
| 5517 } | |
| 5557 return ast_context()->ReturnValue(Pop()); | 5518 return ast_context()->ReturnValue(Pop()); |
| 5558 | 5519 |
| 5559 } else { | 5520 } else { |
| 5560 // Keyed store. | 5521 // Keyed store. |
| 5561 CHECK_ALIVE(VisitForValue(prop->key())); | 5522 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5562 CHECK_ALIVE(VisitForValue(expr->value())); | 5523 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5563 HValue* value = Pop(); | 5524 HValue* value = Pop(); |
| 5564 HValue* key = Pop(); | 5525 HValue* key = Pop(); |
| 5565 HValue* object = Pop(); | 5526 HValue* object = Pop(); |
| 5566 bool has_side_effects = false; | 5527 bool has_side_effects = false; |
| 5567 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 5528 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
| 5568 expr->position(), | 5529 expr->position(), |
| 5569 true, // is_store | 5530 true, // is_store |
| 5570 &has_side_effects); | 5531 &has_side_effects); |
| 5571 Push(value); | 5532 Push(value); |
| 5572 ASSERT(has_side_effects); // Stores always have side effects. | 5533 ASSERT(has_side_effects); // Stores always have side effects. |
| 5573 AddSimulate(expr->AssignmentId()); | 5534 AddSimulate(expr->AssignmentId(), true); |
| 5574 return ast_context()->ReturnValue(Pop()); | 5535 return ast_context()->ReturnValue(Pop()); |
| 5575 } | 5536 } |
| 5576 } | 5537 } |
| 5577 | 5538 |
| 5578 | 5539 |
| 5579 // Because not every expression has a position and there is not common | 5540 // Because not every expression has a position and there is not common |
| 5580 // superclass of Assignment and CountOperation, we cannot just pass the | 5541 // superclass of Assignment and CountOperation, we cannot just pass the |
| 5581 // owning expression instead of position and ast_id separately. | 5542 // owning expression instead of position and ast_id separately. |
| 5582 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 5543 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
| 5583 HValue* value, | 5544 HValue* value, |
| 5584 int position, | 5545 int position, |
| 5585 BailoutId ast_id) { | 5546 BailoutId ast_id) { |
| 5586 LookupResult lookup(isolate()); | 5547 LookupResult lookup(isolate()); |
| 5587 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5548 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 5588 if (type == kUseCell) { | 5549 if (type == kUseCell) { |
| 5589 Handle<GlobalObject> global(info()->global_object()); | 5550 Handle<GlobalObject> global(info()->global_object()); |
| 5590 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5551 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5591 HInstruction* instr = | 5552 HInstruction* instr = |
| 5592 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 5553 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
| 5593 instr->set_position(position); | 5554 instr->set_position(position); |
| 5594 AddInstruction(instr); | 5555 AddInstruction(instr); |
| 5595 if (instr->HasObservableSideEffects()) AddSimulate(ast_id); | 5556 if (instr->HasObservableSideEffects()) AddSimulate(ast_id, true); |
| 5596 } else { | 5557 } else { |
| 5597 HValue* context = environment()->LookupContext(); | 5558 HValue* context = environment()->LookupContext(); |
| 5598 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 5559 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 5599 AddInstruction(global_object); | 5560 AddInstruction(global_object); |
| 5600 HStoreGlobalGeneric* instr = | 5561 HStoreGlobalGeneric* instr = |
| 5601 new(zone()) HStoreGlobalGeneric(context, | 5562 new(zone()) HStoreGlobalGeneric(context, |
| 5602 global_object, | 5563 global_object, |
| 5603 var->name(), | 5564 var->name(), |
| 5604 value, | 5565 value, |
| 5605 function_strict_mode_flag()); | 5566 function_strict_mode_flag()); |
| 5606 instr->set_position(position); | 5567 instr->set_position(position); |
| 5607 AddInstruction(instr); | 5568 AddInstruction(instr); |
| 5608 ASSERT(instr->HasObservableSideEffects()); | 5569 ASSERT(instr->HasObservableSideEffects()); |
| 5609 if (instr->HasObservableSideEffects()) AddSimulate(ast_id); | 5570 AddSimulate(ast_id, true); |
| 5610 } | 5571 } |
| 5611 } | 5572 } |
| 5612 | 5573 |
| 5613 | 5574 |
| 5614 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5575 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5615 Expression* target = expr->target(); | 5576 Expression* target = expr->target(); |
| 5616 VariableProxy* proxy = target->AsVariableProxy(); | 5577 VariableProxy* proxy = target->AsVariableProxy(); |
| 5617 Property* prop = target->AsProperty(); | 5578 Property* prop = target->AsProperty(); |
| 5618 ASSERT(proxy == NULL || prop == NULL); | 5579 ASSERT(proxy == NULL || prop == NULL); |
| 5619 | 5580 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5676 UNREACHABLE(); | 5637 UNREACHABLE(); |
| 5677 default: | 5638 default: |
| 5678 mode = HStoreContextSlot::kNoCheck; | 5639 mode = HStoreContextSlot::kNoCheck; |
| 5679 } | 5640 } |
| 5680 | 5641 |
| 5681 HValue* context = BuildContextChainWalk(var); | 5642 HValue* context = BuildContextChainWalk(var); |
| 5682 HStoreContextSlot* instr = | 5643 HStoreContextSlot* instr = |
| 5683 new(zone()) HStoreContextSlot(context, var->index(), mode, Top()); | 5644 new(zone()) HStoreContextSlot(context, var->index(), mode, Top()); |
| 5684 AddInstruction(instr); | 5645 AddInstruction(instr); |
| 5685 if (instr->HasObservableSideEffects()) { | 5646 if (instr->HasObservableSideEffects()) { |
| 5686 AddSimulate(expr->AssignmentId()); | 5647 AddSimulate(expr->AssignmentId(), true); |
| 5687 } | 5648 } |
| 5688 break; | 5649 break; |
| 5689 } | 5650 } |
| 5690 | 5651 |
| 5691 case Variable::LOOKUP: | 5652 case Variable::LOOKUP: |
| 5692 return Bailout("compound assignment to lookup slot"); | 5653 return Bailout("compound assignment to lookup slot"); |
| 5693 } | 5654 } |
| 5694 return ast_context()->ReturnValue(Pop()); | 5655 return ast_context()->ReturnValue(Pop()); |
| 5695 | 5656 |
| 5696 } else if (prop != NULL) { | 5657 } else if (prop != NULL) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 5716 Handle<JSObject> holder; | 5677 Handle<JSObject> holder; |
| 5717 if (LookupGetter(map, name, &getter, &holder)) { | 5678 if (LookupGetter(map, name, &getter, &holder)) { |
| 5718 load = BuildCallGetter(object, map, getter, holder); | 5679 load = BuildCallGetter(object, map, getter, holder); |
| 5719 } else { | 5680 } else { |
| 5720 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 5681 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
| 5721 } | 5682 } |
| 5722 } else { | 5683 } else { |
| 5723 load = BuildLoadNamedGeneric(object, name, prop); | 5684 load = BuildLoadNamedGeneric(object, name, prop); |
| 5724 } | 5685 } |
| 5725 PushAndAdd(load); | 5686 PushAndAdd(load); |
| 5726 if (load->HasObservableSideEffects()) AddSimulate(prop->LoadId()); | 5687 if (load->HasObservableSideEffects()) AddSimulate(prop->LoadId(), true); |
| 5727 | 5688 |
| 5728 CHECK_ALIVE(VisitForValue(expr->value())); | 5689 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5729 HValue* right = Pop(); | 5690 HValue* right = Pop(); |
| 5730 HValue* left = Pop(); | 5691 HValue* left = Pop(); |
| 5731 | 5692 |
| 5732 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5693 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5733 PushAndAdd(instr); | 5694 PushAndAdd(instr); |
| 5734 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); | 5695 if (instr->HasObservableSideEffects()) AddSimulate(operation->id(), true); |
| 5735 | 5696 |
| 5736 HInstruction* store; | 5697 HInstruction* store; |
| 5737 if (!monomorphic) { | 5698 if (!monomorphic) { |
| 5738 // If we don't know the monomorphic type, do a generic store. | 5699 // If we don't know the monomorphic type, do a generic store. |
| 5739 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr)); | 5700 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr)); |
| 5740 } else { | 5701 } else { |
| 5741 Handle<JSFunction> setter; | 5702 Handle<JSFunction> setter; |
| 5742 Handle<JSObject> holder; | 5703 Handle<JSObject> holder; |
| 5743 if (LookupSetter(map, name, &setter, &holder)) { | 5704 if (LookupSetter(map, name, &setter, &holder)) { |
| 5744 store = BuildCallSetter(object, instr, map, setter, holder); | 5705 store = BuildCallSetter(object, instr, map, setter, holder); |
| 5745 } else { | 5706 } else { |
| 5746 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, | 5707 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, |
| 5747 name, | 5708 name, |
| 5748 instr, | 5709 instr, |
| 5749 map)); | 5710 map)); |
| 5750 } | 5711 } |
| 5751 } | 5712 } |
| 5752 AddInstruction(store); | 5713 AddInstruction(store); |
| 5753 // Drop the simulated receiver and value. Return the value. | 5714 // Drop the simulated receiver and value. Return the value. |
| 5754 Drop(2); | 5715 Drop(2); |
| 5755 Push(instr); | 5716 Push(instr); |
| 5756 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 5717 if (store->HasObservableSideEffects()) { |
| 5718 AddSimulate(expr->AssignmentId(), true); | |
| 5719 } | |
| 5757 return ast_context()->ReturnValue(Pop()); | 5720 return ast_context()->ReturnValue(Pop()); |
| 5758 | 5721 |
| 5759 } else { | 5722 } else { |
| 5760 // Keyed property. | 5723 // Keyed property. |
| 5761 CHECK_ALIVE(VisitForValue(prop->obj())); | 5724 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5762 CHECK_ALIVE(VisitForValue(prop->key())); | 5725 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5763 HValue* obj = environment()->ExpressionStackAt(1); | 5726 HValue* obj = environment()->ExpressionStackAt(1); |
| 5764 HValue* key = environment()->ExpressionStackAt(0); | 5727 HValue* key = environment()->ExpressionStackAt(0); |
| 5765 | 5728 |
| 5766 bool has_side_effects = false; | 5729 bool has_side_effects = false; |
| 5767 HValue* load = HandleKeyedElementAccess( | 5730 HValue* load = HandleKeyedElementAccess( |
| 5768 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 5731 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| 5769 false, // is_store | 5732 false, // is_store |
| 5770 &has_side_effects); | 5733 &has_side_effects); |
| 5771 Push(load); | 5734 Push(load); |
| 5772 if (has_side_effects) AddSimulate(prop->LoadId()); | 5735 if (has_side_effects) AddSimulate(prop->LoadId(), true); |
| 5773 | 5736 |
| 5774 | 5737 |
| 5775 CHECK_ALIVE(VisitForValue(expr->value())); | 5738 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5776 HValue* right = Pop(); | 5739 HValue* right = Pop(); |
| 5777 HValue* left = Pop(); | 5740 HValue* left = Pop(); |
| 5778 | 5741 |
| 5779 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5742 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5780 PushAndAdd(instr); | 5743 PushAndAdd(instr); |
| 5781 if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); | 5744 if (instr->HasObservableSideEffects()) AddSimulate(operation->id(), true); |
| 5782 | 5745 |
| 5783 expr->RecordTypeFeedback(oracle(), zone()); | 5746 expr->RecordTypeFeedback(oracle(), zone()); |
| 5784 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), | 5747 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), |
| 5785 RelocInfo::kNoPosition, | 5748 RelocInfo::kNoPosition, |
| 5786 true, // is_store | 5749 true, // is_store |
| 5787 &has_side_effects); | 5750 &has_side_effects); |
| 5788 | 5751 |
| 5789 // Drop the simulated receiver, key, and value. Return the value. | 5752 // Drop the simulated receiver, key, and value. Return the value. |
| 5790 Drop(3); | 5753 Drop(3); |
| 5791 Push(instr); | 5754 Push(instr); |
| 5792 ASSERT(has_side_effects); // Stores always have side effects. | 5755 ASSERT(has_side_effects); // Stores always have side effects. |
| 5793 AddSimulate(expr->AssignmentId()); | 5756 AddSimulate(expr->AssignmentId(), true); |
| 5794 return ast_context()->ReturnValue(Pop()); | 5757 return ast_context()->ReturnValue(Pop()); |
| 5795 } | 5758 } |
| 5796 | 5759 |
| 5797 } else { | 5760 } else { |
| 5798 return Bailout("invalid lhs in compound assignment"); | 5761 return Bailout("invalid lhs in compound assignment"); |
| 5799 } | 5762 } |
| 5800 } | 5763 } |
| 5801 | 5764 |
| 5802 | 5765 |
| 5803 void HGraphBuilder::VisitAssignment(Assignment* expr) { | 5766 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); | 5869 ASSERT(expr->op() == Token::INIT_CONST); |
| 5907 | 5870 |
| 5908 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 5871 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
| 5909 } | 5872 } |
| 5910 | 5873 |
| 5911 HValue* context = BuildContextChainWalk(var); | 5874 HValue* context = BuildContextChainWalk(var); |
| 5912 HStoreContextSlot* instr = new(zone()) HStoreContextSlot( | 5875 HStoreContextSlot* instr = new(zone()) HStoreContextSlot( |
| 5913 context, var->index(), mode, Top()); | 5876 context, var->index(), mode, Top()); |
| 5914 AddInstruction(instr); | 5877 AddInstruction(instr); |
| 5915 if (instr->HasObservableSideEffects()) { | 5878 if (instr->HasObservableSideEffects()) { |
| 5916 AddSimulate(expr->AssignmentId()); | 5879 AddSimulate(expr->AssignmentId(), true); |
| 5917 } | 5880 } |
| 5918 return ast_context()->ReturnValue(Pop()); | 5881 return ast_context()->ReturnValue(Pop()); |
| 5919 } | 5882 } |
| 5920 | 5883 |
| 5921 case Variable::LOOKUP: | 5884 case Variable::LOOKUP: |
| 5922 return Bailout("assignment to LOOKUP variable"); | 5885 return Bailout("assignment to LOOKUP variable"); |
| 5923 } | 5886 } |
| 5924 } else { | 5887 } else { |
| 5925 return Bailout("invalid left-hand side in assignment"); | 5888 return Bailout("invalid left-hand side in assignment"); |
| 5926 } | 5889 } |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6044 case EXTERNAL_PIXEL_ELEMENTS: { | 6007 case EXTERNAL_PIXEL_ELEMENTS: { |
| 6045 val = AddInstruction(new(zone()) HClampToUint8(val)); | 6008 val = AddInstruction(new(zone()) HClampToUint8(val)); |
| 6046 break; | 6009 break; |
| 6047 } | 6010 } |
| 6048 case EXTERNAL_BYTE_ELEMENTS: | 6011 case EXTERNAL_BYTE_ELEMENTS: |
| 6049 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 6012 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 6050 case EXTERNAL_SHORT_ELEMENTS: | 6013 case EXTERNAL_SHORT_ELEMENTS: |
| 6051 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 6014 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 6052 case EXTERNAL_INT_ELEMENTS: | 6015 case EXTERNAL_INT_ELEMENTS: |
| 6053 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | 6016 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; | 6017 break; |
| 6062 } | 6018 } |
| 6063 case EXTERNAL_FLOAT_ELEMENTS: | 6019 case EXTERNAL_FLOAT_ELEMENTS: |
| 6064 case EXTERNAL_DOUBLE_ELEMENTS: | 6020 case EXTERNAL_DOUBLE_ELEMENTS: |
| 6065 break; | 6021 break; |
| 6066 case FAST_SMI_ELEMENTS: | 6022 case FAST_SMI_ELEMENTS: |
| 6067 case FAST_ELEMENTS: | 6023 case FAST_ELEMENTS: |
| 6068 case FAST_DOUBLE_ELEMENTS: | 6024 case FAST_DOUBLE_ELEMENTS: |
| 6069 case FAST_HOLEY_SMI_ELEMENTS: | 6025 case FAST_HOLEY_SMI_ELEMENTS: |
| 6070 case FAST_HOLEY_ELEMENTS: | 6026 case FAST_HOLEY_ELEMENTS: |
| (...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6671 HValue* key = Pop(); | 6627 HValue* key = Pop(); |
| 6672 HValue* obj = Pop(); | 6628 HValue* obj = Pop(); |
| 6673 | 6629 |
| 6674 bool has_side_effects = false; | 6630 bool has_side_effects = false; |
| 6675 HValue* load = HandleKeyedElementAccess( | 6631 HValue* load = HandleKeyedElementAccess( |
| 6676 obj, key, NULL, expr, expr->id(), expr->position(), | 6632 obj, key, NULL, expr, expr->id(), expr->position(), |
| 6677 false, // is_store | 6633 false, // is_store |
| 6678 &has_side_effects); | 6634 &has_side_effects); |
| 6679 if (has_side_effects) { | 6635 if (has_side_effects) { |
| 6680 if (ast_context()->IsEffect()) { | 6636 if (ast_context()->IsEffect()) { |
| 6681 AddSimulate(expr->id()); | 6637 AddSimulate(expr->id(), true); |
| 6682 } else { | 6638 } else { |
| 6683 Push(load); | 6639 Push(load); |
| 6684 AddSimulate(expr->id()); | 6640 AddSimulate(expr->id(), true); |
| 6685 Drop(1); | 6641 Drop(1); |
| 6686 } | 6642 } |
| 6687 } | 6643 } |
| 6688 return ast_context()->ReturnValue(load); | 6644 return ast_context()->ReturnValue(load); |
| 6689 } | 6645 } |
| 6690 instr->set_position(expr->position()); | 6646 instr->set_position(expr->position()); |
| 6691 return ast_context()->ReturnInstruction(instr, expr->id()); | 6647 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 6692 } | 6648 } |
| 6693 | 6649 |
| 6694 | 6650 |
| (...skipping 1228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7923 } | 7879 } |
| 7924 | 7880 |
| 7925 | 7881 |
| 7926 void HGraphBuilder::VisitSub(UnaryOperation* expr) { | 7882 void HGraphBuilder::VisitSub(UnaryOperation* expr) { |
| 7927 CHECK_ALIVE(VisitForValue(expr->expression())); | 7883 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7928 HValue* value = Pop(); | 7884 HValue* value = Pop(); |
| 7929 HValue* context = environment()->LookupContext(); | 7885 HValue* context = environment()->LookupContext(); |
| 7930 HInstruction* instr = | 7886 HInstruction* instr = |
| 7931 new(zone()) HMul(context, value, graph_->GetConstantMinus1()); | 7887 new(zone()) HMul(context, value, graph_->GetConstantMinus1()); |
| 7932 TypeInfo info = oracle()->UnaryType(expr); | 7888 TypeInfo info = oracle()->UnaryType(expr); |
| 7889 Representation rep = ToRepresentation(info); | |
| 7933 if (info.IsUninitialized()) { | 7890 if (info.IsUninitialized()) { |
| 7934 AddInstruction(new(zone()) HSoftDeoptimize); | 7891 AddInstruction(new(zone()) HSoftDeoptimize); |
| 7935 current_block()->MarkAsDeoptimizing(); | 7892 current_block()->MarkAsDeoptimizing(); |
| 7936 info = TypeInfo::Unknown(); | 7893 info = TypeInfo::Unknown(); |
| 7937 } | 7894 } |
| 7938 Representation rep = ToRepresentation(info); | 7895 HBinaryOperation::cast(instr)->set_observed_input_representation( |
| 7939 TraceRepresentation(expr->op(), info, instr, rep); | 7896 rep, rep); |
| 7940 instr->AssumeRepresentation(rep); | |
| 7941 return ast_context()->ReturnInstruction(instr, expr->id()); | 7897 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7942 } | 7898 } |
| 7943 | 7899 |
| 7944 | 7900 |
| 7945 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 7901 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
| 7946 CHECK_ALIVE(VisitForValue(expr->expression())); | 7902 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7947 HValue* value = Pop(); | 7903 HValue* value = Pop(); |
| 7948 TypeInfo info = oracle()->UnaryType(expr); | 7904 TypeInfo info = oracle()->UnaryType(expr); |
| 7949 if (info.IsUninitialized()) { | 7905 if (info.IsUninitialized()) { |
| 7950 AddInstruction(new(zone()) HSoftDeoptimize); | 7906 AddInstruction(new(zone()) HSoftDeoptimize); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8019 } | 7975 } |
| 8020 | 7976 |
| 8021 // The addition has no side effects, so we do not need | 7977 // The addition has no side effects, so we do not need |
| 8022 // to simulate the expression stack after this instruction. | 7978 // to simulate the expression stack after this instruction. |
| 8023 // Any later failures deopt to the load of the input or earlier. | 7979 // Any later failures deopt to the load of the input or earlier. |
| 8024 HConstant* delta = (expr->op() == Token::INC) | 7980 HConstant* delta = (expr->op() == Token::INC) |
| 8025 ? graph_->GetConstant1() | 7981 ? graph_->GetConstant1() |
| 8026 : graph_->GetConstantMinus1(); | 7982 : graph_->GetConstantMinus1(); |
| 8027 HValue* context = environment()->LookupContext(); | 7983 HValue* context = environment()->LookupContext(); |
| 8028 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); | 7984 HInstruction* instr = new(zone()) HAdd(context, Top(), delta); |
| 8029 TraceRepresentation(expr->op(), info, instr, rep); | 7985 // We can't insert a simulate here, because it would break deoptimization, |
| 7986 // so the HAdd must not have side effects, so we must freeze its | |
| 7987 // representation. | |
| 8030 instr->AssumeRepresentation(rep); | 7988 instr->AssumeRepresentation(rep); |
| 7989 instr->ClearAllSideEffects(); | |
| 8031 AddInstruction(instr); | 7990 AddInstruction(instr); |
| 8032 return instr; | 7991 return instr; |
| 8033 } | 7992 } |
| 8034 | 7993 |
| 8035 | 7994 |
| 8036 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { | 7995 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 8037 ASSERT(!HasStackOverflow()); | 7996 ASSERT(!HasStackOverflow()); |
| 8038 ASSERT(current_block() != NULL); | 7997 ASSERT(current_block() != NULL); |
| 8039 ASSERT(current_block()->HasPredecessor()); | 7998 ASSERT(current_block()->HasPredecessor()); |
| 8040 Expression* target = expr->expression(); | 7999 Expression* target = expr->expression(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8094 } | 8053 } |
| 8095 } | 8054 } |
| 8096 | 8055 |
| 8097 HValue* context = BuildContextChainWalk(var); | 8056 HValue* context = BuildContextChainWalk(var); |
| 8098 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 8057 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
| 8099 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 8058 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
| 8100 HStoreContextSlot* instr = | 8059 HStoreContextSlot* instr = |
| 8101 new(zone()) HStoreContextSlot(context, var->index(), mode, after); | 8060 new(zone()) HStoreContextSlot(context, var->index(), mode, after); |
| 8102 AddInstruction(instr); | 8061 AddInstruction(instr); |
| 8103 if (instr->HasObservableSideEffects()) { | 8062 if (instr->HasObservableSideEffects()) { |
| 8104 AddSimulate(expr->AssignmentId()); | 8063 AddSimulate(expr->AssignmentId(), true); |
| 8105 } | 8064 } |
| 8106 break; | 8065 break; |
| 8107 } | 8066 } |
| 8108 | 8067 |
| 8109 case Variable::LOOKUP: | 8068 case Variable::LOOKUP: |
| 8110 return Bailout("lookup variable in count operation"); | 8069 return Bailout("lookup variable in count operation"); |
| 8111 } | 8070 } |
| 8112 | 8071 |
| 8113 } else { | 8072 } else { |
| 8114 // Argument of the count operation is a property. | 8073 // Argument of the count operation is a property. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 8135 Handle<JSObject> holder; | 8094 Handle<JSObject> holder; |
| 8136 if (LookupGetter(map, name, &getter, &holder)) { | 8095 if (LookupGetter(map, name, &getter, &holder)) { |
| 8137 load = BuildCallGetter(object, map, getter, holder); | 8096 load = BuildCallGetter(object, map, getter, holder); |
| 8138 } else { | 8097 } else { |
| 8139 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 8098 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
| 8140 } | 8099 } |
| 8141 } else { | 8100 } else { |
| 8142 load = BuildLoadNamedGeneric(object, name, prop); | 8101 load = BuildLoadNamedGeneric(object, name, prop); |
| 8143 } | 8102 } |
| 8144 PushAndAdd(load); | 8103 PushAndAdd(load); |
| 8145 if (load->HasObservableSideEffects()) AddSimulate(prop->LoadId()); | 8104 if (load->HasObservableSideEffects()) AddSimulate(prop->LoadId(), true); |
| 8146 | 8105 |
| 8147 after = BuildIncrement(returns_original_input, expr); | 8106 after = BuildIncrement(returns_original_input, expr); |
| 8148 input = Pop(); | 8107 input = Pop(); |
| 8149 | 8108 |
| 8150 HInstruction* store; | 8109 HInstruction* store; |
| 8151 if (!monomorphic) { | 8110 if (!monomorphic) { |
| 8152 // If we don't know the monomorphic type, do a generic store. | 8111 // If we don't know the monomorphic type, do a generic store. |
| 8153 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after)); | 8112 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after)); |
| 8154 } else { | 8113 } else { |
| 8155 Handle<JSFunction> setter; | 8114 Handle<JSFunction> setter; |
| 8156 Handle<JSObject> holder; | 8115 Handle<JSObject> holder; |
| 8157 if (LookupSetter(map, name, &setter, &holder)) { | 8116 if (LookupSetter(map, name, &setter, &holder)) { |
| 8158 store = BuildCallSetter(object, after, map, setter, holder); | 8117 store = BuildCallSetter(object, after, map, setter, holder); |
| 8159 } else { | 8118 } else { |
| 8160 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, | 8119 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, |
| 8161 name, | 8120 name, |
| 8162 after, | 8121 after, |
| 8163 map)); | 8122 map)); |
| 8164 } | 8123 } |
| 8165 } | 8124 } |
| 8166 AddInstruction(store); | 8125 AddInstruction(store); |
| 8167 | 8126 |
| 8168 // Overwrite the receiver in the bailout environment with the result | 8127 // Overwrite the receiver in the bailout environment with the result |
| 8169 // of the operation, and the placeholder with the original value if | 8128 // of the operation, and the placeholder with the original value if |
| 8170 // necessary. | 8129 // necessary. |
| 8171 environment()->SetExpressionStackAt(0, after); | 8130 environment()->SetExpressionStackAt(0, after); |
| 8172 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 8131 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
| 8173 if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); | 8132 if (store->HasObservableSideEffects()) { |
| 8133 AddSimulate(expr->AssignmentId(), true); | |
| 8134 } | |
| 8174 | 8135 |
| 8175 } else { | 8136 } else { |
| 8176 // Keyed property. | 8137 // Keyed property. |
| 8177 if (returns_original_input) Push(graph_->GetConstantUndefined()); | 8138 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
| 8178 | 8139 |
| 8179 CHECK_ALIVE(VisitForValue(prop->obj())); | 8140 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 8180 CHECK_ALIVE(VisitForValue(prop->key())); | 8141 CHECK_ALIVE(VisitForValue(prop->key())); |
| 8181 HValue* obj = environment()->ExpressionStackAt(1); | 8142 HValue* obj = environment()->ExpressionStackAt(1); |
| 8182 HValue* key = environment()->ExpressionStackAt(0); | 8143 HValue* key = environment()->ExpressionStackAt(0); |
| 8183 | 8144 |
| 8184 bool has_side_effects = false; | 8145 bool has_side_effects = false; |
| 8185 HValue* load = HandleKeyedElementAccess( | 8146 HValue* load = HandleKeyedElementAccess( |
| 8186 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 8147 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| 8187 false, // is_store | 8148 false, // is_store |
| 8188 &has_side_effects); | 8149 &has_side_effects); |
| 8189 Push(load); | 8150 Push(load); |
| 8190 if (has_side_effects) AddSimulate(prop->LoadId()); | 8151 if (has_side_effects) AddSimulate(prop->LoadId(), true); |
| 8191 | 8152 |
| 8192 after = BuildIncrement(returns_original_input, expr); | 8153 after = BuildIncrement(returns_original_input, expr); |
| 8193 input = Pop(); | 8154 input = Pop(); |
| 8194 | 8155 |
| 8195 expr->RecordTypeFeedback(oracle(), zone()); | 8156 expr->RecordTypeFeedback(oracle(), zone()); |
| 8196 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), | 8157 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), |
| 8197 RelocInfo::kNoPosition, | 8158 RelocInfo::kNoPosition, |
| 8198 true, // is_store | 8159 true, // is_store |
| 8199 &has_side_effects); | 8160 &has_side_effects); |
| 8200 | 8161 |
| 8201 // Drop the key from the bailout environment. Overwrite the receiver | 8162 // Drop the key from the bailout environment. Overwrite the receiver |
| 8202 // with the result of the operation, and the placeholder with the | 8163 // with the result of the operation, and the placeholder with the |
| 8203 // original value if necessary. | 8164 // original value if necessary. |
| 8204 Drop(1); | 8165 Drop(1); |
| 8205 environment()->SetExpressionStackAt(0, after); | 8166 environment()->SetExpressionStackAt(0, after); |
| 8206 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 8167 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
| 8207 ASSERT(has_side_effects); // Stores always have side effects. | 8168 ASSERT(has_side_effects); // Stores always have side effects. |
| 8208 AddSimulate(expr->AssignmentId()); | 8169 AddSimulate(expr->AssignmentId(), true); |
| 8209 } | 8170 } |
| 8210 } | 8171 } |
| 8211 | 8172 |
| 8212 Drop(returns_original_input ? 2 : 1); | 8173 Drop(returns_original_input ? 2 : 1); |
| 8213 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 8174 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
| 8214 } | 8175 } |
| 8215 | 8176 |
| 8216 | 8177 |
| 8217 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, | 8178 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, |
| 8218 HValue* string, | 8179 HValue* string, |
| 8219 HValue* index) { | 8180 HValue* index) { |
| 8220 AddInstruction(new(zone()) HCheckNonSmi(string)); | 8181 AddInstruction(new(zone()) HCheckNonSmi(string)); |
| 8221 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 8182 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 8222 HStringLength* length = new(zone()) HStringLength(string); | 8183 HStringLength* length = new(zone()) HStringLength(string); |
| 8223 AddInstruction(length); | 8184 AddInstruction(length); |
| 8224 HInstruction* checked_index = | 8185 HInstruction* checked_index = |
| 8225 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 8186 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
| 8226 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 8187 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
| 8227 } | 8188 } |
| 8228 | 8189 |
| 8229 | 8190 |
| 8230 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, | 8191 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
| 8231 HValue* left, | 8192 HValue* left, |
| 8232 HValue* right) { | 8193 HValue* right) { |
| 8233 HValue* context = environment()->LookupContext(); | 8194 HValue* context = environment()->LookupContext(); |
| 8234 TypeInfo info = oracle()->BinaryType(expr); | 8195 TypeInfo left_info, right_info, result_info, combined_info; |
| 8235 if (info.IsUninitialized()) { | 8196 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); |
| 8197 Representation left_rep = ToRepresentation(left_info); | |
| 8198 Representation right_rep = ToRepresentation(right_info); | |
| 8199 Representation result_rep = ToRepresentation(result_info); | |
| 8200 if (left_info.IsUninitialized()) { | |
| 8201 // Can't have initialized one but not the other. | |
| 8202 ASSERT(right_info.IsUninitialized()); | |
| 8236 AddInstruction(new(zone()) HSoftDeoptimize); | 8203 AddInstruction(new(zone()) HSoftDeoptimize); |
| 8237 current_block()->MarkAsDeoptimizing(); | 8204 current_block()->MarkAsDeoptimizing(); |
| 8238 info = TypeInfo::Unknown(); | 8205 left_info = right_info = TypeInfo::Unknown(); |
| 8239 } | 8206 } |
| 8240 HInstruction* instr = NULL; | 8207 HInstruction* instr = NULL; |
| 8241 switch (expr->op()) { | 8208 switch (expr->op()) { |
| 8242 case Token::ADD: | 8209 case Token::ADD: |
| 8243 if (info.IsString()) { | 8210 if (left_info.IsString() && right_info.IsString()) { |
| 8244 AddInstruction(new(zone()) HCheckNonSmi(left)); | 8211 AddInstruction(new(zone()) HCheckNonSmi(left)); |
| 8245 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 8212 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 8246 AddInstruction(new(zone()) HCheckNonSmi(right)); | 8213 AddInstruction(new(zone()) HCheckNonSmi(right)); |
| 8247 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 8214 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 8248 instr = new(zone()) HStringAdd(context, left, right); | 8215 instr = new(zone()) HStringAdd(context, left, right); |
| 8249 } else { | 8216 } else { |
| 8250 instr = HAdd::NewHAdd(zone(), context, left, right); | 8217 instr = HAdd::NewHAdd(zone(), context, left, right); |
| 8251 } | 8218 } |
| 8252 break; | 8219 break; |
| 8253 case Token::SUB: | 8220 case Token::SUB: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8285 if (can_be_shift_by_zero) graph()->RecordUint32Instruction(instr); | 8252 if (can_be_shift_by_zero) graph()->RecordUint32Instruction(instr); |
| 8286 } | 8253 } |
| 8287 break; | 8254 break; |
| 8288 case Token::SHL: | 8255 case Token::SHL: |
| 8289 instr = HShl::NewHShl(zone(), context, left, right); | 8256 instr = HShl::NewHShl(zone(), context, left, right); |
| 8290 break; | 8257 break; |
| 8291 default: | 8258 default: |
| 8292 UNREACHABLE(); | 8259 UNREACHABLE(); |
| 8293 } | 8260 } |
| 8294 | 8261 |
| 8295 // If we hit an uninitialized binary op stub we will get type info | 8262 if (instr->IsBinaryOperation()) { |
| 8296 // for a smi operation. If one of the operands is a constant string | 8263 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
| 8297 // do not generate code assuming it is a smi operation. | 8264 binop->set_observed_input_representation(left_rep, right_rep); |
| 8298 if (info.IsSmi() && | 8265 binop->initialize_output_representation(result_rep); |
| 8299 ((left->IsConstant() && HConstant::cast(left)->handle()->IsString()) || | |
| 8300 (right->IsConstant() && HConstant::cast(right)->handle()->IsString()))) { | |
| 8301 return instr; | |
| 8302 } | 8266 } |
| 8303 Representation rep = ToRepresentation(info); | |
| 8304 // We only generate either int32 or generic tagged bitwise operations. | |
| 8305 if (instr->IsBitwiseBinaryOperation()) { | |
| 8306 HBitwiseBinaryOperation::cast(instr)-> | |
| 8307 InitializeObservedInputRepresentation(rep); | |
| 8308 if (rep.IsDouble()) rep = Representation::Integer32(); | |
| 8309 } | |
| 8310 TraceRepresentation(expr->op(), info, instr, rep); | |
| 8311 instr->AssumeRepresentation(rep); | |
| 8312 return instr; | 8267 return instr; |
| 8313 } | 8268 } |
| 8314 | 8269 |
| 8315 | 8270 |
| 8316 // Check for the form (%_ClassOf(foo) === 'BarClass'). | 8271 // Check for the form (%_ClassOf(foo) === 'BarClass'). |
| 8317 static bool IsClassOfTest(CompareOperation* expr) { | 8272 static bool IsClassOfTest(CompareOperation* expr) { |
| 8318 if (expr->op() != Token::EQ_STRICT) return false; | 8273 if (expr->op() != Token::EQ_STRICT) return false; |
| 8319 CallRuntime* call = expr->left()->AsCallRuntime(); | 8274 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 8320 if (call == NULL) return false; | 8275 if (call == NULL) return false; |
| 8321 Literal* literal = expr->right()->AsLiteral(); | 8276 Literal* literal = expr->right()->AsLiteral(); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8445 CHECK_ALIVE(VisitForValue(expr->left())); | 8400 CHECK_ALIVE(VisitForValue(expr->left())); |
| 8446 CHECK_ALIVE(VisitForValue(expr->right())); | 8401 CHECK_ALIVE(VisitForValue(expr->right())); |
| 8447 HValue* right = Pop(); | 8402 HValue* right = Pop(); |
| 8448 HValue* left = Pop(); | 8403 HValue* left = Pop(); |
| 8449 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8404 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
| 8450 instr->set_position(expr->position()); | 8405 instr->set_position(expr->position()); |
| 8451 return ast_context()->ReturnInstruction(instr, expr->id()); | 8406 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8452 } | 8407 } |
| 8453 | 8408 |
| 8454 | 8409 |
| 8455 void HGraphBuilder::TraceRepresentation(Token::Value op, | |
| 8456 TypeInfo info, | |
| 8457 HValue* value, | |
| 8458 Representation rep) { | |
| 8459 if (!FLAG_trace_representation) return; | |
| 8460 // TODO(svenpanne) Under which circumstances are we actually not flexible? | |
| 8461 // At first glance, this looks a bit weird... | |
| 8462 bool flexible = value->CheckFlag(HValue::kFlexibleRepresentation); | |
| 8463 PrintF("Operation %s has type info %s, %schange representation assumption " | |
| 8464 "for %s (ID %d) from %s to %s\n", | |
| 8465 Token::Name(op), | |
| 8466 info.ToString(), | |
| 8467 flexible ? "" : " DO NOT ", | |
| 8468 value->Mnemonic(), | |
| 8469 graph_->GetMaximumValueID(), | |
| 8470 value->representation().Mnemonic(), | |
| 8471 rep.Mnemonic()); | |
| 8472 } | |
| 8473 | |
| 8474 | |
| 8475 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { | 8410 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { |
| 8411 if (info.IsUninitialized()) return Representation::None(); | |
| 8476 if (info.IsSmi()) return Representation::Integer32(); | 8412 if (info.IsSmi()) return Representation::Integer32(); |
| 8477 if (info.IsInteger32()) return Representation::Integer32(); | 8413 if (info.IsInteger32()) return Representation::Integer32(); |
| 8478 if (info.IsDouble()) return Representation::Double(); | 8414 if (info.IsDouble()) return Representation::Double(); |
| 8479 if (info.IsNumber()) return Representation::Double(); | 8415 if (info.IsNumber()) return Representation::Double(); |
| 8480 return Representation::Tagged(); | 8416 return Representation::Tagged(); |
| 8481 } | 8417 } |
| 8482 | 8418 |
| 8483 | 8419 |
| 8484 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8420 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
| 8485 HTypeof* typeof_expr, | 8421 HTypeof* typeof_expr, |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8563 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8499 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8564 HValue* value = Pop(); | 8500 HValue* value = Pop(); |
| 8565 Literal* literal = expr->right()->AsLiteral(); | 8501 Literal* literal = expr->right()->AsLiteral(); |
| 8566 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 8502 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
| 8567 HClassOfTestAndBranch* instr = | 8503 HClassOfTestAndBranch* instr = |
| 8568 new(zone()) HClassOfTestAndBranch(value, rhs); | 8504 new(zone()) HClassOfTestAndBranch(value, rhs); |
| 8569 instr->set_position(expr->position()); | 8505 instr->set_position(expr->position()); |
| 8570 return ast_context()->ReturnControl(instr, expr->id()); | 8506 return ast_context()->ReturnControl(instr, expr->id()); |
| 8571 } | 8507 } |
| 8572 | 8508 |
| 8573 TypeInfo type_info = oracle()->CompareType(expr); | 8509 TypeInfo left_type, right_type, overall_type_info; |
| 8510 oracle()->CompareType(expr, &left_type, &right_type, &overall_type_info); | |
| 8511 Representation combined_rep = ToRepresentation(overall_type_info); | |
| 8512 Representation left_rep = ToRepresentation(left_type); | |
| 8513 Representation right_rep = ToRepresentation(right_type); | |
| 8574 // Check if this expression was ever executed according to type feedback. | 8514 // Check if this expression was ever executed according to type feedback. |
| 8575 // Note that for the special typeof/null/undefined cases we get unknown here. | 8515 // Note that for the special typeof/null/undefined cases we get unknown here. |
| 8576 if (type_info.IsUninitialized()) { | 8516 if (overall_type_info.IsUninitialized()) { |
| 8577 AddInstruction(new(zone()) HSoftDeoptimize); | 8517 AddInstruction(new(zone()) HSoftDeoptimize); |
| 8578 current_block()->MarkAsDeoptimizing(); | 8518 current_block()->MarkAsDeoptimizing(); |
| 8579 type_info = TypeInfo::Unknown(); | 8519 overall_type_info = left_type = right_type = TypeInfo::Unknown(); |
| 8580 } | 8520 } |
| 8581 | 8521 |
| 8582 CHECK_ALIVE(VisitForValue(expr->left())); | 8522 CHECK_ALIVE(VisitForValue(expr->left())); |
| 8583 CHECK_ALIVE(VisitForValue(expr->right())); | 8523 CHECK_ALIVE(VisitForValue(expr->right())); |
| 8584 | 8524 |
| 8585 HValue* context = environment()->LookupContext(); | 8525 HValue* context = environment()->LookupContext(); |
| 8586 HValue* right = Pop(); | 8526 HValue* right = Pop(); |
| 8587 HValue* left = Pop(); | 8527 HValue* left = Pop(); |
| 8588 Token::Value op = expr->op(); | 8528 Token::Value op = expr->op(); |
| 8589 | 8529 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8641 AddInstruction(new(zone()) HCheckFunction(right, target)); | 8581 AddInstruction(new(zone()) HCheckFunction(right, target)); |
| 8642 HInstanceOfKnownGlobal* result = | 8582 HInstanceOfKnownGlobal* result = |
| 8643 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 8583 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
| 8644 result->set_position(expr->position()); | 8584 result->set_position(expr->position()); |
| 8645 return ast_context()->ReturnInstruction(result, expr->id()); | 8585 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8646 } | 8586 } |
| 8647 } else if (op == Token::IN) { | 8587 } else if (op == Token::IN) { |
| 8648 HIn* result = new(zone()) HIn(context, left, right); | 8588 HIn* result = new(zone()) HIn(context, left, right); |
| 8649 result->set_position(expr->position()); | 8589 result->set_position(expr->position()); |
| 8650 return ast_context()->ReturnInstruction(result, expr->id()); | 8590 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8651 } else if (type_info.IsNonPrimitive()) { | 8591 } else if (overall_type_info.IsNonPrimitive()) { |
| 8652 switch (op) { | 8592 switch (op) { |
| 8653 case Token::EQ: | 8593 case Token::EQ: |
| 8654 case Token::EQ_STRICT: { | 8594 case Token::EQ_STRICT: { |
| 8655 // Can we get away with map check and not instance type check? | 8595 // Can we get away with map check and not instance type check? |
| 8656 Handle<Map> map = oracle()->GetCompareMap(expr); | 8596 Handle<Map> map = oracle()->GetCompareMap(expr); |
| 8657 if (!map.is_null()) { | 8597 if (!map.is_null()) { |
| 8658 AddCheckMapsWithTransitions(left, map); | 8598 AddCheckMapsWithTransitions(left, map); |
| 8659 AddCheckMapsWithTransitions(right, map); | 8599 AddCheckMapsWithTransitions(right, map); |
| 8660 HCompareObjectEqAndBranch* result = | 8600 HCompareObjectEqAndBranch* result = |
| 8661 new(zone()) HCompareObjectEqAndBranch(left, right); | 8601 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 8662 result->set_position(expr->position()); | 8602 result->set_position(expr->position()); |
| 8663 return ast_context()->ReturnControl(result, expr->id()); | 8603 return ast_context()->ReturnControl(result, expr->id()); |
| 8664 } else { | 8604 } else { |
| 8665 AddInstruction(new(zone()) HCheckNonSmi(left)); | 8605 AddInstruction(new(zone()) HCheckNonSmi(left)); |
| 8666 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8606 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
| 8667 AddInstruction(new(zone()) HCheckNonSmi(right)); | 8607 AddInstruction(new(zone()) HCheckNonSmi(right)); |
| 8668 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8608 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
| 8669 HCompareObjectEqAndBranch* result = | 8609 HCompareObjectEqAndBranch* result = |
| 8670 new(zone()) HCompareObjectEqAndBranch(left, right); | 8610 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 8671 result->set_position(expr->position()); | 8611 result->set_position(expr->position()); |
| 8672 return ast_context()->ReturnControl(result, expr->id()); | 8612 return ast_context()->ReturnControl(result, expr->id()); |
| 8673 } | 8613 } |
| 8674 } | 8614 } |
| 8675 default: | 8615 default: |
| 8676 return Bailout("Unsupported non-primitive compare"); | 8616 return Bailout("Unsupported non-primitive compare"); |
| 8677 } | 8617 } |
| 8678 } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && | 8618 } else if (overall_type_info.IsSymbol() && Token::IsEqualityOp(op)) { |
| 8679 (op == Token::EQ || op == Token::EQ_STRICT)) { | |
| 8680 AddInstruction(new(zone()) HCheckNonSmi(left)); | 8619 AddInstruction(new(zone()) HCheckNonSmi(left)); |
| 8681 AddInstruction(HCheckInstanceType::NewIsSymbol(left, zone())); | 8620 AddInstruction(HCheckInstanceType::NewIsSymbol(left, zone())); |
| 8682 AddInstruction(new(zone()) HCheckNonSmi(right)); | 8621 AddInstruction(new(zone()) HCheckNonSmi(right)); |
| 8683 AddInstruction(HCheckInstanceType::NewIsSymbol(right, zone())); | 8622 AddInstruction(HCheckInstanceType::NewIsSymbol(right, zone())); |
| 8684 HCompareObjectEqAndBranch* result = | 8623 HCompareObjectEqAndBranch* result = |
| 8685 new(zone()) HCompareObjectEqAndBranch(left, right); | 8624 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 8686 result->set_position(expr->position()); | 8625 result->set_position(expr->position()); |
| 8687 return ast_context()->ReturnControl(result, expr->id()); | 8626 return ast_context()->ReturnControl(result, expr->id()); |
| 8688 } else { | 8627 } else { |
| 8689 Representation r = ToRepresentation(type_info); | 8628 if (combined_rep.IsTagged() || combined_rep.IsNone()) { |
| 8690 if (r.IsTagged()) { | |
| 8691 HCompareGeneric* result = | 8629 HCompareGeneric* result = |
| 8692 new(zone()) HCompareGeneric(context, left, right, op); | 8630 new(zone()) HCompareGeneric(context, left, right, op); |
| 8631 result->set_observed_input_representation(left_rep, right_rep); | |
| 8693 result->set_position(expr->position()); | 8632 result->set_position(expr->position()); |
| 8694 return ast_context()->ReturnInstruction(result, expr->id()); | 8633 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8695 } else { | 8634 } else { |
| 8696 HCompareIDAndBranch* result = | 8635 HCompareIDAndBranch* result = |
| 8697 new(zone()) HCompareIDAndBranch(left, right, op); | 8636 new(zone()) HCompareIDAndBranch(left, right, op); |
| 8637 result->set_observed_input_representation(left_rep, right_rep); | |
| 8698 result->set_position(expr->position()); | 8638 result->set_position(expr->position()); |
| 8699 result->SetInputRepresentation(r); | |
| 8700 return ast_context()->ReturnControl(result, expr->id()); | 8639 return ast_context()->ReturnControl(result, expr->id()); |
| 8701 } | 8640 } |
| 8702 } | 8641 } |
| 8703 } | 8642 } |
| 8704 | 8643 |
| 8705 | 8644 |
| 8706 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8645 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 8707 HValue* value, | 8646 HValue* value, |
| 8708 NilValue nil) { | 8647 NilValue nil) { |
| 8709 ASSERT(!HasStackOverflow()); | 8648 ASSERT(!HasStackOverflow()); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8776 environment()->Bind(variable, value); | 8715 environment()->Bind(variable, value); |
| 8777 } | 8716 } |
| 8778 break; | 8717 break; |
| 8779 case Variable::CONTEXT: | 8718 case Variable::CONTEXT: |
| 8780 if (hole_init) { | 8719 if (hole_init) { |
| 8781 HValue* value = graph()->GetConstantHole(); | 8720 HValue* value = graph()->GetConstantHole(); |
| 8782 HValue* context = environment()->LookupContext(); | 8721 HValue* context = environment()->LookupContext(); |
| 8783 HStoreContextSlot* store = new(zone()) HStoreContextSlot( | 8722 HStoreContextSlot* store = new(zone()) HStoreContextSlot( |
| 8784 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8723 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
| 8785 AddInstruction(store); | 8724 AddInstruction(store); |
| 8786 if (store->HasObservableSideEffects()) AddSimulate(proxy->id()); | 8725 if (store->HasObservableSideEffects()) AddSimulate(proxy->id(), true); |
| 8787 } | 8726 } |
| 8788 break; | 8727 break; |
| 8789 case Variable::LOOKUP: | 8728 case Variable::LOOKUP: |
| 8790 return Bailout("unsupported lookup slot in declaration"); | 8729 return Bailout("unsupported lookup slot in declaration"); |
| 8791 } | 8730 } |
| 8792 } | 8731 } |
| 8793 | 8732 |
| 8794 | 8733 |
| 8795 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) { | 8734 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) { |
| 8796 VariableProxy* proxy = declaration->proxy(); | 8735 VariableProxy* proxy = declaration->proxy(); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 8812 environment()->Bind(variable, value); | 8751 environment()->Bind(variable, value); |
| 8813 break; | 8752 break; |
| 8814 } | 8753 } |
| 8815 case Variable::CONTEXT: { | 8754 case Variable::CONTEXT: { |
| 8816 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8755 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 8817 HValue* value = Pop(); | 8756 HValue* value = Pop(); |
| 8818 HValue* context = environment()->LookupContext(); | 8757 HValue* context = environment()->LookupContext(); |
| 8819 HStoreContextSlot* store = new(zone()) HStoreContextSlot( | 8758 HStoreContextSlot* store = new(zone()) HStoreContextSlot( |
| 8820 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8759 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
| 8821 AddInstruction(store); | 8760 AddInstruction(store); |
| 8822 if (store->HasObservableSideEffects()) AddSimulate(proxy->id()); | 8761 if (store->HasObservableSideEffects()) AddSimulate(proxy->id(), true); |
| 8823 break; | 8762 break; |
| 8824 } | 8763 } |
| 8825 case Variable::LOOKUP: | 8764 case Variable::LOOKUP: |
| 8826 return Bailout("unsupported lookup slot in declaration"); | 8765 return Bailout("unsupported lookup slot in declaration"); |
| 8827 } | 8766 } |
| 8828 } | 8767 } |
| 8829 | 8768 |
| 8830 | 8769 |
| 8831 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 8770 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
| 8832 UNREACHABLE(); | 8771 UNREACHABLE(); |
| (...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9955 } | 9894 } |
| 9956 } | 9895 } |
| 9957 | 9896 |
| 9958 #ifdef DEBUG | 9897 #ifdef DEBUG |
| 9959 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9898 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 9960 if (allocator_ != NULL) allocator_->Verify(); | 9899 if (allocator_ != NULL) allocator_->Verify(); |
| 9961 #endif | 9900 #endif |
| 9962 } | 9901 } |
| 9963 | 9902 |
| 9964 } } // namespace v8::internal | 9903 } } // namespace v8::internal |
| OLD | NEW |