Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/hydrogen.cc

Issue 7060010: Merge bleeding edge into the GC branch up to 7948. The asserts (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 if (first_ == NULL) { 108 if (first_ == NULL) {
109 HBlockEntry* entry = new(zone()) HBlockEntry(); 109 HBlockEntry* entry = new(zone()) HBlockEntry();
110 entry->InitializeAsFirst(this); 110 entry->InitializeAsFirst(this);
111 first_ = last_ = entry; 111 first_ = last_ = entry;
112 } 112 }
113 instr->InsertAfter(last_); 113 instr->InsertAfter(last_);
114 last_ = instr; 114 last_ = instr;
115 } 115 }
116 116
117 117
118 HDeoptimize* HBasicBlock::CreateDeoptimize() { 118 HDeoptimize* HBasicBlock::CreateDeoptimize(
119 HDeoptimize::UseEnvironment has_uses) {
119 ASSERT(HasEnvironment()); 120 ASSERT(HasEnvironment());
121 if (has_uses == HDeoptimize::kNoUses) return new(zone()) HDeoptimize(0);
122
120 HEnvironment* environment = last_environment(); 123 HEnvironment* environment = last_environment();
121
122 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length()); 124 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length());
123
124 for (int i = 0; i < environment->length(); i++) { 125 for (int i = 0; i < environment->length(); i++) {
125 HValue* val = environment->values()->at(i); 126 HValue* val = environment->values()->at(i);
126 instr->AddEnvironmentValue(val); 127 instr->AddEnvironmentValue(val);
127 } 128 }
128 129
129 return instr; 130 return instr;
130 } 131 }
131 132
132 133
133 HSimulate* HBasicBlock::CreateSimulate(int id) { 134 HSimulate* HBasicBlock::CreateSimulate(int id) {
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 void TraceGVN(const char* msg, ...) { 1014 void TraceGVN(const char* msg, ...) {
1014 if (FLAG_trace_gvn) { 1015 if (FLAG_trace_gvn) {
1015 va_list arguments; 1016 va_list arguments;
1016 va_start(arguments, msg); 1017 va_start(arguments, msg);
1017 OS::VPrint(msg, arguments); 1018 OS::VPrint(msg, arguments);
1018 va_end(arguments); 1019 va_end(arguments);
1019 } 1020 }
1020 } 1021 }
1021 1022
1022 1023
1023 HValueMap::HValueMap(const HValueMap* other) 1024 HValueMap::HValueMap(Zone* zone, const HValueMap* other)
1024 : array_size_(other->array_size_), 1025 : array_size_(other->array_size_),
1025 lists_size_(other->lists_size_), 1026 lists_size_(other->lists_size_),
1026 count_(other->count_), 1027 count_(other->count_),
1027 present_flags_(other->present_flags_), 1028 present_flags_(other->present_flags_),
1028 array_(ZONE->NewArray<HValueMapListElement>(other->array_size_)), 1029 array_(zone->NewArray<HValueMapListElement>(other->array_size_)),
1029 lists_(ZONE->NewArray<HValueMapListElement>(other->lists_size_)), 1030 lists_(zone->NewArray<HValueMapListElement>(other->lists_size_)),
1030 free_list_head_(other->free_list_head_) { 1031 free_list_head_(other->free_list_head_) {
1031 memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement)); 1032 memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement));
1032 memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement)); 1033 memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement));
1033 } 1034 }
1034 1035
1035 1036
1036 void HValueMap::Kill(int flags) { 1037 void HValueMap::Kill(int flags) {
1037 int depends_flags = HValue::ConvertChangesToDependsFlags(flags); 1038 int depends_flags = HValue::ConvertChangesToDependsFlags(flags);
1038 if ((present_flags_ & depends_flags) == 0) return; 1039 if ((present_flags_ & depends_flags) == 0) return;
1039 present_flags_ = 0; 1040 present_flags_ = 0;
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1232 while (instr != NULL) { 1233 while (instr != NULL) {
1233 if (instr->IsGoto()) { 1234 if (instr->IsGoto()) {
1234 HGoto::cast(instr)->set_include_stack_check(false); 1235 HGoto::cast(instr)->set_include_stack_check(false);
1235 return; 1236 return;
1236 } 1237 }
1237 instr = instr->next(); 1238 instr = instr->next();
1238 } 1239 }
1239 } 1240 }
1240 1241
1241 1242
1243 // Simple sparse set with O(1) add, contains, and clear.
1244 class SparseSet {
1245 public:
1246 SparseSet(Zone* zone, int capacity)
1247 : capacity_(capacity),
1248 length_(0),
1249 dense_(zone->NewArray<int>(capacity)),
1250 sparse_(zone->NewArray<int>(capacity)) {}
1251
1252 bool Contains(int n) const {
1253 ASSERT(0 <= n && n < capacity_);
1254 int d = sparse_[n];
1255 return 0 <= d && d < length_ && dense_[d] == n;
1256 }
1257
1258 bool Add(int n) {
1259 if (Contains(n)) return false;
1260 dense_[length_] = n;
1261 sparse_[n] = length_;
1262 ++length_;
1263 return true;
1264 }
1265
1266 void Clear() { length_ = 0; }
1267
1268 private:
1269 int capacity_;
1270 int length_;
1271 int* dense_;
1272 int* sparse_;
1273
1274 DISALLOW_COPY_AND_ASSIGN(SparseSet);
1275 };
1276
1277
1242 class HGlobalValueNumberer BASE_EMBEDDED { 1278 class HGlobalValueNumberer BASE_EMBEDDED {
1243 public: 1279 public:
1244 explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info) 1280 explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
1245 : graph_(graph), 1281 : graph_(graph),
1246 info_(info), 1282 info_(info),
1247 block_side_effects_(graph_->blocks()->length()), 1283 block_side_effects_(graph->blocks()->length()),
1248 loop_side_effects_(graph_->blocks()->length()) { 1284 loop_side_effects_(graph->blocks()->length()),
1285 visited_on_paths_(graph->zone(), graph->blocks()->length()) {
1249 ASSERT(info->isolate()->heap()->allow_allocation(false)); 1286 ASSERT(info->isolate()->heap()->allow_allocation(false));
1250 block_side_effects_.AddBlock(0, graph_->blocks()->length()); 1287 block_side_effects_.AddBlock(0, graph_->blocks()->length());
1251 loop_side_effects_.AddBlock(0, graph_->blocks()->length()); 1288 loop_side_effects_.AddBlock(0, graph_->blocks()->length());
1252 } 1289 }
1253 ~HGlobalValueNumberer() { 1290 ~HGlobalValueNumberer() {
1254 ASSERT(!info_->isolate()->heap()->allow_allocation(true)); 1291 ASSERT(!info_->isolate()->heap()->allow_allocation(true));
1255 } 1292 }
1256 1293
1257 void Analyze(); 1294 void Analyze();
1258 1295
1259 private: 1296 private:
1297 int CollectSideEffectsOnPathsToDominatedBlock(HBasicBlock* dominator,
1298 HBasicBlock* dominated);
1260 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); 1299 void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
1261 void ComputeBlockSideEffects(); 1300 void ComputeBlockSideEffects();
1262 void LoopInvariantCodeMotion(); 1301 void LoopInvariantCodeMotion();
1263 void ProcessLoopBlock(HBasicBlock* block, 1302 void ProcessLoopBlock(HBasicBlock* block,
1264 HBasicBlock* before_loop, 1303 HBasicBlock* before_loop,
1265 int loop_kills); 1304 int loop_kills);
1266 bool AllowCodeMotion(); 1305 bool AllowCodeMotion();
1267 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); 1306 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1268 1307
1269 HGraph* graph() { return graph_; } 1308 HGraph* graph() { return graph_; }
1270 CompilationInfo* info() { return info_; } 1309 CompilationInfo* info() { return info_; }
1271 Zone* zone() { return graph_->zone(); } 1310 Zone* zone() { return graph_->zone(); }
1272 1311
1273 HGraph* graph_; 1312 HGraph* graph_;
1274 CompilationInfo* info_; 1313 CompilationInfo* info_;
1275 1314
1276 // A map of block IDs to their side effects. 1315 // A map of block IDs to their side effects.
1277 ZoneList<int> block_side_effects_; 1316 ZoneList<int> block_side_effects_;
1278 1317
1279 // A map of loop header block IDs to their loop's side effects. 1318 // A map of loop header block IDs to their loop's side effects.
1280 ZoneList<int> loop_side_effects_; 1319 ZoneList<int> loop_side_effects_;
1320
1321 // Used when collecting side effects on paths from dominator to
1322 // dominated.
1323 SparseSet visited_on_paths_;
1281 }; 1324 };
1282 1325
1283 1326
1284 void HGlobalValueNumberer::Analyze() { 1327 void HGlobalValueNumberer::Analyze() {
1285 ComputeBlockSideEffects(); 1328 ComputeBlockSideEffects();
1286 if (FLAG_loop_invariant_code_motion) { 1329 if (FLAG_loop_invariant_code_motion) {
1287 LoopInvariantCodeMotion(); 1330 LoopInvariantCodeMotion();
1288 } 1331 }
1289 HValueMap* map = new(zone()) HValueMap(); 1332 HValueMap* map = new(zone()) HValueMap();
1290 AnalyzeBlock(graph_->blocks()->at(0), map); 1333 AnalyzeBlock(graph_->blocks()->at(0), map);
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 if (!found) { 1449 if (!found) {
1407 result = false; 1450 result = false;
1408 break; 1451 break;
1409 } 1452 }
1410 } 1453 }
1411 } 1454 }
1412 return result; 1455 return result;
1413 } 1456 }
1414 1457
1415 1458
1459 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
1460 HBasicBlock* dominator, HBasicBlock* dominated) {
1461 int side_effects = 0;
1462 for (int i = 0; i < dominated->predecessors()->length(); ++i) {
1463 HBasicBlock* block = dominated->predecessors()->at(i);
1464 if (dominator->block_id() < block->block_id() &&
1465 block->block_id() < dominated->block_id() &&
1466 visited_on_paths_.Add(block->block_id())) {
1467 side_effects |= block_side_effects_[block->block_id()];
1468 side_effects |= CollectSideEffectsOnPathsToDominatedBlock(
1469 dominator, block);
1470 }
1471 }
1472 return side_effects;
1473 }
1474
1475
1416 void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { 1476 void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
1417 TraceGVN("Analyzing block B%d\n", block->block_id()); 1477 TraceGVN("Analyzing block B%d%s\n",
1478 block->block_id(),
1479 block->IsLoopHeader() ? " (loop header)" : "");
1418 1480
1419 // If this is a loop header kill everything killed by the loop. 1481 // If this is a loop header kill everything killed by the loop.
1420 if (block->IsLoopHeader()) { 1482 if (block->IsLoopHeader()) {
1421 map->Kill(loop_side_effects_[block->block_id()]); 1483 map->Kill(loop_side_effects_[block->block_id()]);
1422 } 1484 }
1423 1485
1424 // Go through all instructions of the current block. 1486 // Go through all instructions of the current block.
1425 HInstruction* instr = block->first(); 1487 HInstruction* instr = block->first();
1426 while (instr != NULL) { 1488 while (instr != NULL) {
1427 HInstruction* next = instr->next(); 1489 HInstruction* next = instr->next();
(...skipping 20 matching lines...) Expand all
1448 instr = next; 1510 instr = next;
1449 } 1511 }
1450 1512
1451 // Recursively continue analysis for all immediately dominated blocks. 1513 // Recursively continue analysis for all immediately dominated blocks.
1452 int length = block->dominated_blocks()->length(); 1514 int length = block->dominated_blocks()->length();
1453 for (int i = 0; i < length; ++i) { 1515 for (int i = 0; i < length; ++i) {
1454 HBasicBlock* dominated = block->dominated_blocks()->at(i); 1516 HBasicBlock* dominated = block->dominated_blocks()->at(i);
1455 // No need to copy the map for the last child in the dominator tree. 1517 // No need to copy the map for the last child in the dominator tree.
1456 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); 1518 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone());
1457 1519
1458 // If the dominated block is not a successor to this block we have to 1520 // Kill everything killed on any path between this block and the
1459 // kill everything killed on any path between this block and the 1521 // dominated block.
1460 // dominated block. Note we rely on the block ordering. 1522 // We don't have to traverse these paths if the value map is
1461 bool is_successor = false; 1523 // already empty.
1462 int predecessor_count = dominated->predecessors()->length(); 1524 // If the range of block ids (block_id, dominated_id) is empty
1463 for (int j = 0; !is_successor && j < predecessor_count; ++j) { 1525 // there are no such paths.
1464 is_successor = (dominated->predecessors()->at(j) == block); 1526 if (!successor_map->IsEmpty() &&
1527 block->block_id() + 1 < dominated->block_id()) {
1528 visited_on_paths_.Clear();
1529 successor_map->Kill(CollectSideEffectsOnPathsToDominatedBlock(block,
1530 dominated));
1465 } 1531 }
1466
1467 if (!is_successor) {
1468 int side_effects = 0;
1469 for (int j = block->block_id() + 1; j < dominated->block_id(); ++j) {
1470 side_effects |= block_side_effects_[j];
1471 }
1472 successor_map->Kill(side_effects);
1473 }
1474
1475 AnalyzeBlock(dominated, successor_map); 1532 AnalyzeBlock(dominated, successor_map);
1476 } 1533 }
1477 } 1534 }
1478 1535
1479 1536
1480 class HInferRepresentation BASE_EMBEDDED { 1537 class HInferRepresentation BASE_EMBEDDED {
1481 public: 1538 public:
1482 explicit HInferRepresentation(HGraph* graph) 1539 explicit HInferRepresentation(HGraph* graph)
1483 : graph_(graph), worklist_(8), in_worklist_(graph->GetMaximumValueID()) {} 1540 : graph_(graph), worklist_(8), in_worklist_(graph->GetMaximumValueID()) {}
1484 1541
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
1795 HValue* use_value = it.value(); 1852 HValue* use_value = it.value();
1796 int use_index = it.index(); 1853 int use_index = it.index();
1797 Representation req = use_value->RequiredInputRepresentation(use_index); 1854 Representation req = use_value->RequiredInputRepresentation(use_index);
1798 if (req.IsNone() || req.Equals(r)) continue; 1855 if (req.IsNone() || req.Equals(r)) continue;
1799 InsertRepresentationChangeForUse(value, use_value, use_index, req); 1856 InsertRepresentationChangeForUse(value, use_value, use_index, req);
1800 } 1857 }
1801 if (value->HasNoUses()) { 1858 if (value->HasNoUses()) {
1802 ASSERT(value->IsConstant()); 1859 ASSERT(value->IsConstant());
1803 value->DeleteAndReplaceWith(NULL); 1860 value->DeleteAndReplaceWith(NULL);
1804 } 1861 }
1862
1863 // The only purpose of a HForceRepresentation is to represent the value
1864 // after the (possible) HChange instruction. We make it disappear.
1865 if (value->IsForceRepresentation()) {
1866 value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
1867 }
1805 } 1868 }
1806 1869
1807 1870
1808 void HGraph::InsertRepresentationChanges() { 1871 void HGraph::InsertRepresentationChanges() {
1809 HPhase phase("Insert representation changes", this); 1872 HPhase phase("Insert representation changes", this);
1810 1873
1811 1874
1812 // Compute truncation flag for phis: Initially assume that all 1875 // Compute truncation flag for phis: Initially assume that all
1813 // int32-phis allow truncation and iteratively remove the ones that 1876 // int32-phis allow truncation and iteratively remove the ones that
1814 // are used in an operation that does not allow a truncating 1877 // are used in an operation that does not allow a truncating
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
2222 // We don't yet handle the function name for named function expressions. 2285 // We don't yet handle the function name for named function expressions.
2223 if (scope->function() != NULL) return Bailout("named function expression"); 2286 if (scope->function() != NULL) return Bailout("named function expression");
2224 2287
2225 HConstant* undefined_constant = new(zone()) HConstant( 2288 HConstant* undefined_constant = new(zone()) HConstant(
2226 isolate()->factory()->undefined_value(), Representation::Tagged()); 2289 isolate()->factory()->undefined_value(), Representation::Tagged());
2227 AddInstruction(undefined_constant); 2290 AddInstruction(undefined_constant);
2228 graph_->set_undefined_constant(undefined_constant); 2291 graph_->set_undefined_constant(undefined_constant);
2229 2292
2230 // Set the initial values of parameters including "this". "This" has 2293 // Set the initial values of parameters including "this". "This" has
2231 // parameter index 0. 2294 // parameter index 0.
2232 int count = scope->num_parameters() + 1; 2295 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
2233 for (int i = 0; i < count; ++i) { 2296
2297 for (int i = 0; i < environment()->parameter_count(); ++i) {
2234 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); 2298 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i));
2235 environment()->Bind(i, parameter); 2299 environment()->Bind(i, parameter);
2236 } 2300 }
2237 2301
2238 // Set the initial values of stack-allocated locals. 2302 // First special is HContext.
2239 for (int i = count; i < environment()->length(); ++i) { 2303 HInstruction* context = AddInstruction(new(zone()) HContext);
2304 environment()->BindContext(context);
2305
2306 // Initialize specials and locals to undefined.
2307 for (int i = environment()->parameter_count() + 1;
2308 i < environment()->length();
2309 ++i) {
2240 environment()->Bind(i, undefined_constant); 2310 environment()->Bind(i, undefined_constant);
2241 } 2311 }
2242 2312
2243 // Handle the arguments and arguments shadow variables specially (they do 2313 // Handle the arguments and arguments shadow variables specially (they do
2244 // not have declarations). 2314 // not have declarations).
2245 if (scope->arguments() != NULL) { 2315 if (scope->arguments() != NULL) {
2246 if (!scope->arguments()->IsStackAllocated() || 2316 if (!scope->arguments()->IsStackAllocated() ||
2247 (scope->arguments_shadow() != NULL && 2317 (scope->arguments_shadow() != NULL &&
2248 !scope->arguments_shadow()->IsStackAllocated())) { 2318 !scope->arguments_shadow()->IsStackAllocated())) {
2249 return Bailout("context-allocated arguments"); 2319 return Bailout("context-allocated arguments");
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
2476 for (int i = 0; i < clause_count; ++i) { 2546 for (int i = 0; i < clause_count; ++i) {
2477 CaseClause* clause = clauses->at(i); 2547 CaseClause* clause = clauses->at(i);
2478 if (clause->is_default()) continue; 2548 if (clause->is_default()) continue;
2479 if (!clause->label()->IsSmiLiteral()) { 2549 if (!clause->label()->IsSmiLiteral()) {
2480 return Bailout("SwitchStatement: non-literal switch label"); 2550 return Bailout("SwitchStatement: non-literal switch label");
2481 } 2551 }
2482 2552
2483 // Unconditionally deoptimize on the first non-smi compare. 2553 // Unconditionally deoptimize on the first non-smi compare.
2484 clause->RecordTypeFeedback(oracle()); 2554 clause->RecordTypeFeedback(oracle());
2485 if (!clause->IsSmiCompare()) { 2555 if (!clause->IsSmiCompare()) {
2486 current_block()->FinishExitWithDeoptimization(); 2556 // Finish with deoptimize and add uses of enviroment values to
2557 // account for invisible uses.
2558 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
2487 set_current_block(NULL); 2559 set_current_block(NULL);
2488 break; 2560 break;
2489 } 2561 }
2490 2562
2491 // Otherwise generate a compare and branch. 2563 // Otherwise generate a compare and branch.
2492 CHECK_ALIVE(VisitForValue(clause->label())); 2564 CHECK_ALIVE(VisitForValue(clause->label()));
2493 HValue* label_value = Pop(); 2565 HValue* label_value = Pop();
2494 HCompare* compare = 2566 HCompare* compare =
2495 new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); 2567 new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT);
2496 compare->SetInputRepresentation(Representation::Integer32()); 2568 compare->SetInputRepresentation(Representation::Integer32());
(...skipping 15 matching lines...) Expand all
2512 HBasicBlock* curr_test_block = first_test_block; 2584 HBasicBlock* curr_test_block = first_test_block;
2513 HBasicBlock* fall_through_block = NULL; 2585 HBasicBlock* fall_through_block = NULL;
2514 BreakAndContinueInfo break_info(stmt); 2586 BreakAndContinueInfo break_info(stmt);
2515 { BreakAndContinueScope push(&break_info, this); 2587 { BreakAndContinueScope push(&break_info, this);
2516 for (int i = 0; i < clause_count; ++i) { 2588 for (int i = 0; i < clause_count; ++i) {
2517 CaseClause* clause = clauses->at(i); 2589 CaseClause* clause = clauses->at(i);
2518 2590
2519 // Identify the block where normal (non-fall-through) control flow 2591 // Identify the block where normal (non-fall-through) control flow
2520 // goes to. 2592 // goes to.
2521 HBasicBlock* normal_block = NULL; 2593 HBasicBlock* normal_block = NULL;
2522 if (clause->is_default() && last_block != NULL) { 2594 if (clause->is_default()) {
2523 normal_block = last_block; 2595 if (last_block != NULL) {
2524 last_block = NULL; // Cleared to indicate we've handled it. 2596 normal_block = last_block;
2597 last_block = NULL; // Cleared to indicate we've handled it.
2598 }
2525 } else if (!curr_test_block->end()->IsDeoptimize()) { 2599 } else if (!curr_test_block->end()->IsDeoptimize()) {
2526 normal_block = curr_test_block->end()->FirstSuccessor(); 2600 normal_block = curr_test_block->end()->FirstSuccessor();
2527 curr_test_block = curr_test_block->end()->SecondSuccessor(); 2601 curr_test_block = curr_test_block->end()->SecondSuccessor();
2528 } 2602 }
2529 2603
2530 // Identify a block to emit the body into. 2604 // Identify a block to emit the body into.
2531 if (normal_block == NULL) { 2605 if (normal_block == NULL) {
2532 if (fall_through_block == NULL) { 2606 if (fall_through_block == NULL) {
2533 // (a) Unreachable. 2607 // (a) Unreachable.
2534 if (clause->is_default()) { 2608 if (clause->is_default()) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2586 HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry); 2660 HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry);
2587 current_block()->Finish(test); 2661 current_block()->Finish(test);
2588 2662
2589 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 2663 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2590 non_osr_entry->Goto(loop_predecessor); 2664 non_osr_entry->Goto(loop_predecessor);
2591 2665
2592 set_current_block(osr_entry); 2666 set_current_block(osr_entry);
2593 int osr_entry_id = statement->OsrEntryId(); 2667 int osr_entry_id = statement->OsrEntryId();
2594 // We want the correct environment at the OsrEntry instruction. Build 2668 // We want the correct environment at the OsrEntry instruction. Build
2595 // it explicitly. The expression stack should be empty. 2669 // it explicitly. The expression stack should be empty.
2596 int count = environment()->length(); 2670 ASSERT(environment()->ExpressionStackIsEmpty());
2597 ASSERT(count == 2671 for (int i = 0; i < environment()->length(); ++i) {
2598 (environment()->parameter_count() + environment()->local_count())); 2672 HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
2599 for (int i = 0; i < count; ++i) { 2673 AddInstruction(osr_value);
2600 HUnknownOSRValue* unknown = new(zone()) HUnknownOSRValue; 2674 environment()->Bind(i, osr_value);
2601 AddInstruction(unknown);
2602 environment()->Bind(i, unknown);
2603 } 2675 }
2604 2676
2605 AddSimulate(osr_entry_id); 2677 AddSimulate(osr_entry_id);
2606 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); 2678 AddInstruction(new(zone()) HOsrEntry(osr_entry_id));
2679 HContext* context = new(zone()) HContext;
2680 AddInstruction(context);
2681 environment()->BindContext(context);
2607 current_block()->Goto(loop_predecessor); 2682 current_block()->Goto(loop_predecessor);
2608 loop_predecessor->SetJoinId(statement->EntryId()); 2683 loop_predecessor->SetJoinId(statement->EntryId());
2609 set_current_block(loop_predecessor); 2684 set_current_block(loop_predecessor);
2610 } 2685 }
2611 2686
2612 2687
2613 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 2688 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
2614 ASSERT(!HasStackOverflow()); 2689 ASSERT(!HasStackOverflow());
2615 ASSERT(current_block() != NULL); 2690 ASSERT(current_block() != NULL);
2616 ASSERT(current_block()->HasPredecessor()); 2691 ASSERT(current_block()->HasPredecessor());
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
2879 lookup->holder() != *global) { 2954 lookup->holder() != *global) {
2880 return kUseGeneric; 2955 return kUseGeneric;
2881 } 2956 }
2882 2957
2883 return kUseCell; 2958 return kUseCell;
2884 } 2959 }
2885 2960
2886 2961
2887 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { 2962 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
2888 ASSERT(var->IsContextSlot()); 2963 ASSERT(var->IsContextSlot());
2889 HInstruction* context = new(zone()) HContext; 2964 HValue* context = environment()->LookupContext();
2890 AddInstruction(context);
2891 int length = info()->scope()->ContextChainLength(var->scope()); 2965 int length = info()->scope()->ContextChainLength(var->scope());
2892 while (length-- > 0) { 2966 while (length-- > 0) {
2893 context = new(zone()) HOuterContext(context); 2967 HInstruction* context_instruction = new(zone()) HOuterContext(context);
2894 AddInstruction(context); 2968 AddInstruction(context_instruction);
2969 context = context_instruction;
2895 } 2970 }
2896 return context; 2971 return context;
2897 } 2972 }
2898 2973
2899 2974
2900 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 2975 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
2901 ASSERT(!HasStackOverflow()); 2976 ASSERT(!HasStackOverflow());
2902 ASSERT(current_block() != NULL); 2977 ASSERT(current_block() != NULL);
2903 ASSERT(current_block()->HasPredecessor()); 2978 ASSERT(current_block()->HasPredecessor());
2904 Variable* variable = expr->AsVariable(); 2979 Variable* variable = expr->AsVariable();
(...skipping 18 matching lines...) Expand all
2923 type = kUseGeneric; 2998 type = kUseGeneric;
2924 } 2999 }
2925 3000
2926 if (type == kUseCell) { 3001 if (type == kUseCell) {
2927 Handle<GlobalObject> global(info()->global_object()); 3002 Handle<GlobalObject> global(info()->global_object());
2928 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3003 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
2929 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 3004 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
2930 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); 3005 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole);
2931 ast_context()->ReturnInstruction(instr, expr->id()); 3006 ast_context()->ReturnInstruction(instr, expr->id());
2932 } else { 3007 } else {
2933 HContext* context = new(zone()) HContext; 3008 HValue* context = environment()->LookupContext();
2934 AddInstruction(context);
2935 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3009 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
2936 AddInstruction(global_object); 3010 AddInstruction(global_object);
2937 HLoadGlobalGeneric* instr = 3011 HLoadGlobalGeneric* instr =
2938 new(zone()) HLoadGlobalGeneric(context, 3012 new(zone()) HLoadGlobalGeneric(context,
2939 global_object, 3013 global_object,
2940 variable->name(), 3014 variable->name(),
2941 ast_context()->is_for_typeof()); 3015 ast_context()->is_for_typeof());
2942 instr->set_position(expr->position()); 3016 instr->set_position(expr->position());
2943 ASSERT(instr->HasSideEffects()); 3017 ASSERT(instr->HasSideEffects());
2944 ast_context()->ReturnInstruction(instr, expr->id()); 3018 ast_context()->ReturnInstruction(instr, expr->id());
(...skipping 22 matching lines...) Expand all
2967 expr->flags(), 3041 expr->flags(),
2968 expr->literal_index()); 3042 expr->literal_index());
2969 ast_context()->ReturnInstruction(instr, expr->id()); 3043 ast_context()->ReturnInstruction(instr, expr->id());
2970 } 3044 }
2971 3045
2972 3046
2973 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 3047 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
2974 ASSERT(!HasStackOverflow()); 3048 ASSERT(!HasStackOverflow());
2975 ASSERT(current_block() != NULL); 3049 ASSERT(current_block() != NULL);
2976 ASSERT(current_block()->HasPredecessor()); 3050 ASSERT(current_block()->HasPredecessor());
2977 HContext* context = new(zone()) HContext; 3051 HValue* context = environment()->LookupContext();
2978 AddInstruction(context);
2979 HObjectLiteral* literal = 3052 HObjectLiteral* literal =
2980 new(zone()) HObjectLiteral(context, 3053 new(zone()) HObjectLiteral(context,
2981 expr->constant_properties(), 3054 expr->constant_properties(),
2982 expr->fast_elements(), 3055 expr->fast_elements(),
2983 expr->literal_index(), 3056 expr->literal_index(),
2984 expr->depth(), 3057 expr->depth(),
2985 expr->has_function()); 3058 expr->has_function());
2986 // The object is expected in the bailout environment during computation 3059 // The object is expected in the bailout environment during computation
2987 // of the property values and is the value of the entire expression. 3060 // of the property values and is the value of the entire expression.
2988 PushAndAdd(literal); 3061 PushAndAdd(literal);
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
3150 // enable elimination of redundant checks after the transition store. 3223 // enable elimination of redundant checks after the transition store.
3151 instr->SetFlag(HValue::kChangesMaps); 3224 instr->SetFlag(HValue::kChangesMaps);
3152 } 3225 }
3153 return instr; 3226 return instr;
3154 } 3227 }
3155 3228
3156 3229
3157 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, 3230 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3158 Handle<String> name, 3231 Handle<String> name,
3159 HValue* value) { 3232 HValue* value) {
3160 HContext* context = new(zone()) HContext; 3233 HValue* context = environment()->LookupContext();
3161 AddInstruction(context);
3162 return new(zone()) HStoreNamedGeneric( 3234 return new(zone()) HStoreNamedGeneric(
3163 context, 3235 context,
3164 object, 3236 object,
3165 name, 3237 name,
3166 value, 3238 value,
3167 function_strict_mode()); 3239 function_strict_mode());
3168 } 3240 }
3169 3241
3170 3242
3171 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, 3243 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
3225 current_block()->Goto(join); 3297 current_block()->Goto(join);
3226 3298
3227 set_current_block(if_false); 3299 set_current_block(if_false);
3228 } 3300 }
3229 } 3301 }
3230 3302
3231 // Finish up. Unconditionally deoptimize if we've handled all the maps we 3303 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3232 // know about and do not want to handle ones we've never seen. Otherwise 3304 // know about and do not want to handle ones we've never seen. Otherwise
3233 // use a generic IC. 3305 // use a generic IC.
3234 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 3306 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3235 current_block()->FinishExitWithDeoptimization(); 3307 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
3236 } else { 3308 } else {
3237 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 3309 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3238 instr->set_position(expr->position()); 3310 instr->set_position(expr->position());
3239 AddInstruction(instr); 3311 AddInstruction(instr);
3240 3312
3241 if (join != NULL) { 3313 if (join != NULL) {
3242 if (!ast_context()->IsEffect()) Push(value); 3314 if (!ast_context()->IsEffect()) Push(value);
3243 current_block()->Goto(join); 3315 current_block()->Goto(join);
3244 } else { 3316 } else {
3245 // The HSimulate for the store should not see the stored value in 3317 // The HSimulate for the store should not see the stored value in
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
3327 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); 3399 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
3328 if (type == kUseCell) { 3400 if (type == kUseCell) {
3329 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 3401 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3330 Handle<GlobalObject> global(info()->global_object()); 3402 Handle<GlobalObject> global(info()->global_object());
3331 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3403 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3332 HInstruction* instr = new(zone()) HStoreGlobalCell(value, cell, check_hole); 3404 HInstruction* instr = new(zone()) HStoreGlobalCell(value, cell, check_hole);
3333 instr->set_position(position); 3405 instr->set_position(position);
3334 AddInstruction(instr); 3406 AddInstruction(instr);
3335 if (instr->HasSideEffects()) AddSimulate(ast_id); 3407 if (instr->HasSideEffects()) AddSimulate(ast_id);
3336 } else { 3408 } else {
3337 HContext* context = new(zone()) HContext; 3409 HValue* context = environment()->LookupContext();
3338 AddInstruction(context);
3339 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3410 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3340 AddInstruction(global_object); 3411 AddInstruction(global_object);
3341 HStoreGlobalGeneric* instr = 3412 HStoreGlobalGeneric* instr =
3342 new(zone()) HStoreGlobalGeneric(context, 3413 new(zone()) HStoreGlobalGeneric(context,
3343 global_object, 3414 global_object,
3344 var->name(), 3415 var->name(),
3345 value, 3416 value,
3346 function_strict_mode()); 3417 function_strict_mode());
3347 instr->set_position(position); 3418 instr->set_position(position);
3348 AddInstruction(instr); 3419 AddInstruction(instr);
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
3553 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; 3624 int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
3554 return new(zone()) HLoadNamedField(object, false, offset); 3625 return new(zone()) HLoadNamedField(object, false, offset);
3555 } 3626 }
3556 } 3627 }
3557 3628
3558 3629
3559 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, 3630 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
3560 Property* expr) { 3631 Property* expr) {
3561 ASSERT(expr->key()->IsPropertyName()); 3632 ASSERT(expr->key()->IsPropertyName());
3562 Handle<Object> name = expr->key()->AsLiteral()->handle(); 3633 Handle<Object> name = expr->key()->AsLiteral()->handle();
3563 HContext* context = new(zone()) HContext; 3634 HValue* context = environment()->LookupContext();
3564 AddInstruction(context);
3565 return new(zone()) HLoadNamedGeneric(context, obj, name); 3635 return new(zone()) HLoadNamedGeneric(context, obj, name);
3566 } 3636 }
3567 3637
3568 3638
3569 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, 3639 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
3570 Property* expr, 3640 Property* expr,
3571 Handle<Map> map, 3641 Handle<Map> map,
3572 Handle<String> name) { 3642 Handle<String> name) {
3573 LookupResult lookup; 3643 LookupResult lookup;
3574 map->LookupInDescriptors(NULL, *name, &lookup); 3644 map->LookupInDescriptors(NULL, *name, &lookup);
3575 if (lookup.IsProperty() && lookup.type() == FIELD) { 3645 if (lookup.IsProperty() && lookup.type() == FIELD) {
3576 return BuildLoadNamedField(obj, 3646 return BuildLoadNamedField(obj,
3577 expr, 3647 expr,
3578 map, 3648 map,
3579 &lookup, 3649 &lookup,
3580 true); 3650 true);
3581 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { 3651 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
3582 AddInstruction(new(zone()) HCheckNonSmi(obj)); 3652 AddInstruction(new(zone()) HCheckNonSmi(obj));
3583 AddInstruction(new(zone()) HCheckMap(obj, map)); 3653 AddInstruction(new(zone()) HCheckMap(obj, map));
3584 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); 3654 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
3585 return new(zone()) HConstant(function, Representation::Tagged()); 3655 return new(zone()) HConstant(function, Representation::Tagged());
3586 } else { 3656 } else {
3587 return BuildLoadNamedGeneric(obj, expr); 3657 return BuildLoadNamedGeneric(obj, expr);
3588 } 3658 }
3589 } 3659 }
3590 3660
3591 3661
3592 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3662 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3593 HValue* key) { 3663 HValue* key) {
3594 HContext* context = new(zone()) HContext; 3664 HValue* context = environment()->LookupContext();
3595 AddInstruction(context);
3596 return new(zone()) HLoadKeyedGeneric(context, object, key); 3665 return new(zone()) HLoadKeyedGeneric(context, object, key);
3597 } 3666 }
3598 3667
3599 3668
3600 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, 3669 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
3601 HValue* key, 3670 HValue* key,
3602 Property* expr) { 3671 Property* expr) {
3603 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3672 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3604 AddInstruction(new(zone()) HCheckNonSmi(object)); 3673 AddInstruction(new(zone()) HCheckNonSmi(object));
3605 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3674 Handle<Map> map = expr->GetMonomorphicReceiverType();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
3660 return BuildLoadKeyedFastElement(obj, key, prop); 3729 return BuildLoadKeyedFastElement(obj, key, prop);
3661 } 3730 }
3662 } 3731 }
3663 return BuildLoadKeyedGeneric(obj, key); 3732 return BuildLoadKeyedGeneric(obj, key);
3664 } 3733 }
3665 3734
3666 3735
3667 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 3736 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3668 HValue* key, 3737 HValue* key,
3669 HValue* value) { 3738 HValue* value) {
3670 HContext* context = new(zone()) HContext; 3739 HValue* context = environment()->LookupContext();
3671 AddInstruction(context);
3672 return new(zone()) HStoreKeyedGeneric( 3740 return new(zone()) HStoreKeyedGeneric(
3673 context, 3741 context,
3674 object, 3742 object,
3675 key, 3743 key,
3676 value, 3744 value,
3677 function_strict_mode()); 3745 function_strict_mode());
3678 } 3746 }
3679 3747
3680 3748
3681 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object, 3749 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3714 ASSERT(map->has_external_array_elements()); 3782 ASSERT(map->has_external_array_elements());
3715 AddInstruction(new(zone()) HCheckMap(object, map)); 3783 AddInstruction(new(zone()) HCheckMap(object, map));
3716 HLoadElements* elements = new(zone()) HLoadElements(object); 3784 HLoadElements* elements = new(zone()) HLoadElements(object);
3717 AddInstruction(elements); 3785 AddInstruction(elements);
3718 HInstruction* length = AddInstruction( 3786 HInstruction* length = AddInstruction(
3719 new(zone()) HExternalArrayLength(elements)); 3787 new(zone()) HExternalArrayLength(elements));
3720 AddInstruction(new(zone()) HBoundsCheck(key, length)); 3788 AddInstruction(new(zone()) HBoundsCheck(key, length));
3721 HLoadExternalArrayPointer* external_elements = 3789 HLoadExternalArrayPointer* external_elements =
3722 new(zone()) HLoadExternalArrayPointer(elements); 3790 new(zone()) HLoadExternalArrayPointer(elements);
3723 AddInstruction(external_elements); 3791 AddInstruction(external_elements);
3792 if (expr->external_array_type() == kExternalPixelArray) {
3793 HClampToUint8* clamp = new(zone()) HClampToUint8(val);
3794 AddInstruction(clamp);
3795 val = clamp;
3796 }
3724 return new(zone()) HStoreKeyedSpecializedArrayElement( 3797 return new(zone()) HStoreKeyedSpecializedArrayElement(
3725 external_elements, 3798 external_elements,
3726 key, 3799 key,
3727 val, 3800 val,
3728 expr->external_array_type()); 3801 expr->external_array_type());
3729 } 3802 }
3730 3803
3731 3804
3732 HInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object, 3805 HInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object,
3733 HValue* key, 3806 HValue* key,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
3789 expr->RecordTypeFeedback(oracle()); 3862 expr->RecordTypeFeedback(oracle());
3790 3863
3791 if (TryArgumentsAccess(expr)) return; 3864 if (TryArgumentsAccess(expr)) return;
3792 3865
3793 CHECK_ALIVE(VisitForValue(expr->obj())); 3866 CHECK_ALIVE(VisitForValue(expr->obj()));
3794 3867
3795 HInstruction* instr = NULL; 3868 HInstruction* instr = NULL;
3796 if (expr->IsArrayLength()) { 3869 if (expr->IsArrayLength()) {
3797 HValue* array = Pop(); 3870 HValue* array = Pop();
3798 AddInstruction(new(zone()) HCheckNonSmi(array)); 3871 AddInstruction(new(zone()) HCheckNonSmi(array));
3799 AddInstruction(new(zone()) HCheckInstanceType(array, 3872 AddInstruction(HCheckInstanceType::NewIsJSArray(array));
3800 JS_ARRAY_TYPE,
3801 JS_ARRAY_TYPE));
3802 instr = new(zone()) HJSArrayLength(array); 3873 instr = new(zone()) HJSArrayLength(array);
3803 3874
3804 } else if (expr->IsStringLength()) { 3875 } else if (expr->IsStringLength()) {
3805 HValue* string = Pop(); 3876 HValue* string = Pop();
3806 AddInstruction(new(zone()) HCheckNonSmi(string)); 3877 AddInstruction(new(zone()) HCheckNonSmi(string));
3807 AddInstruction(new(zone()) HCheckInstanceType(string, 3878 AddInstruction(HCheckInstanceType::NewIsString(string));
3808 FIRST_STRING_TYPE,
3809 LAST_STRING_TYPE));
3810 instr = new(zone()) HStringLength(string); 3879 instr = new(zone()) HStringLength(string);
3811 } else if (expr->IsStringAccess()) { 3880 } else if (expr->IsStringAccess()) {
3812 CHECK_ALIVE(VisitForValue(expr->key())); 3881 CHECK_ALIVE(VisitForValue(expr->key()));
3813 HValue* index = Pop(); 3882 HValue* index = Pop();
3814 HValue* string = Pop(); 3883 HValue* string = Pop();
3815 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); 3884 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
3816 AddInstruction(char_code); 3885 AddInstruction(char_code);
3817 instr = new(zone()) HStringCharFromCode(char_code); 3886 instr = new(zone()) HStringCharFromCode(char_code);
3818 3887
3819 } else if (expr->IsFunctionPrototype()) { 3888 } else if (expr->IsFunctionPrototype()) {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
3912 3981
3913 if (current_block() != NULL) current_block()->Goto(join); 3982 if (current_block() != NULL) current_block()->Goto(join);
3914 set_current_block(if_false); 3983 set_current_block(if_false);
3915 } 3984 }
3916 } 3985 }
3917 3986
3918 // Finish up. Unconditionally deoptimize if we've handled all the maps we 3987 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3919 // know about and do not want to handle ones we've never seen. Otherwise 3988 // know about and do not want to handle ones we've never seen. Otherwise
3920 // use a generic IC. 3989 // use a generic IC.
3921 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 3990 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3922 current_block()->FinishExitWithDeoptimization(); 3991 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
3923 } else { 3992 } else {
3924 HContext* context = new(zone()) HContext; 3993 HValue* context = environment()->LookupContext();
3925 AddInstruction(context);
3926 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); 3994 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
3927 call->set_position(expr->position()); 3995 call->set_position(expr->position());
3928 PreProcessCall(call); 3996 PreProcessCall(call);
3929 3997
3930 if (join != NULL) { 3998 if (join != NULL) {
3931 AddInstruction(call); 3999 AddInstruction(call);
3932 if (!ast_context()->IsEffect()) Push(call); 4000 if (!ast_context()->IsEffect()) Push(call);
3933 current_block()->Goto(join); 4001 current_block()->Goto(join);
3934 } else { 4002 } else {
3935 ast_context()->ReturnInstruction(call, expr->id()); 4003 ast_context()->ReturnInstruction(call, expr->id());
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
4342 4410
4343 CHECK_ALIVE(VisitForValue(prop->key())); 4411 CHECK_ALIVE(VisitForValue(prop->key()));
4344 // Push receiver and key like the non-optimized code generator expects it. 4412 // Push receiver and key like the non-optimized code generator expects it.
4345 HValue* key = Pop(); 4413 HValue* key = Pop();
4346 HValue* receiver = Pop(); 4414 HValue* receiver = Pop();
4347 Push(key); 4415 Push(key);
4348 Push(receiver); 4416 Push(receiver);
4349 4417
4350 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4418 CHECK_ALIVE(VisitExpressions(expr->arguments()));
4351 4419
4352 HContext* context = new(zone()) HContext; 4420 HValue* context = environment()->LookupContext();
4353 AddInstruction(context);
4354 call = PreProcessCall( 4421 call = PreProcessCall(
4355 new(zone()) HCallKeyed(context, key, argument_count)); 4422 new(zone()) HCallKeyed(context, key, argument_count));
4356 call->set_position(expr->position()); 4423 call->set_position(expr->position());
4357 Drop(1); // Key. 4424 Drop(1); // Key.
4358 ast_context()->ReturnInstruction(call, expr->id()); 4425 ast_context()->ReturnInstruction(call, expr->id());
4359 return; 4426 return;
4360 } 4427 }
4361 4428
4362 // Named function call. 4429 // Named function call.
4363 expr->RecordTypeFeedback(oracle()); 4430 expr->RecordTypeFeedback(oracle());
(...skipping 18 matching lines...) Expand all
4382 receiver_map, 4449 receiver_map,
4383 expr->check_type())) { 4450 expr->check_type())) {
4384 return; 4451 return;
4385 } 4452 }
4386 4453
4387 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || 4454 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) ||
4388 expr->check_type() != RECEIVER_MAP_CHECK) { 4455 expr->check_type() != RECEIVER_MAP_CHECK) {
4389 // When the target has a custom call IC generator, use the IC, 4456 // When the target has a custom call IC generator, use the IC,
4390 // because it is likely to generate better code. Also use the IC 4457 // because it is likely to generate better code. Also use the IC
4391 // when a primitive receiver check is required. 4458 // when a primitive receiver check is required.
4392 HContext* context = new(zone()) HContext; 4459 HValue* context = environment()->LookupContext();
4393 AddInstruction(context);
4394 call = PreProcessCall( 4460 call = PreProcessCall(
4395 new(zone()) HCallNamed(context, name, argument_count)); 4461 new(zone()) HCallNamed(context, name, argument_count));
4396 } else { 4462 } else {
4397 AddCheckConstantFunction(expr, receiver, receiver_map, true); 4463 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4398 4464
4399 if (TryInline(expr)) return; 4465 if (TryInline(expr)) return;
4400 call = PreProcessCall( 4466 call = PreProcessCall(
4401 new(zone()) HCallConstantFunction(expr->target(), 4467 new(zone()) HCallConstantFunction(expr->target(),
4402 argument_count)); 4468 argument_count));
4403 } 4469 }
4404 } else if (types != NULL && types->length() > 1) { 4470 } else if (types != NULL && types->length() > 1) {
4405 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 4471 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
4406 HandlePolymorphicCallNamed(expr, receiver, types, name); 4472 HandlePolymorphicCallNamed(expr, receiver, types, name);
4407 return; 4473 return;
4408 4474
4409 } else { 4475 } else {
4410 HContext* context = new(zone()) HContext; 4476 HValue* context = environment()->LookupContext();
4411 AddInstruction(context);
4412 call = PreProcessCall( 4477 call = PreProcessCall(
4413 new(zone()) HCallNamed(context, name, argument_count)); 4478 new(zone()) HCallNamed(context, name, argument_count));
4414 } 4479 }
4415 4480
4416 } else { 4481 } else {
4417 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4482 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4418 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); 4483 bool global_call = (var != NULL) && var->is_global() && !var->is_this();
4419 4484
4420 if (!global_call) { 4485 if (!global_call) {
4421 ++argument_count; 4486 ++argument_count;
4422 CHECK_ALIVE(VisitForValue(expr->expression())); 4487 CHECK_ALIVE(VisitForValue(expr->expression()));
4423 } 4488 }
4424 4489
4425 if (global_call) { 4490 if (global_call) {
4426 bool known_global_function = false; 4491 bool known_global_function = false;
4427 // If there is a global property cell for the name at compile time and 4492 // If there is a global property cell for the name at compile time and
4428 // access check is not enabled we assume that the function will not change 4493 // access check is not enabled we assume that the function will not change
4429 // and generate optimized code for calling the function. 4494 // and generate optimized code for calling the function.
4430 LookupResult lookup; 4495 LookupResult lookup;
4431 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 4496 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
4432 if (type == kUseCell && 4497 if (type == kUseCell &&
4433 !info()->global_object()->IsAccessCheckNeeded()) { 4498 !info()->global_object()->IsAccessCheckNeeded()) {
4434 Handle<GlobalObject> global(info()->global_object()); 4499 Handle<GlobalObject> global(info()->global_object());
4435 known_global_function = expr->ComputeGlobalTarget(global, &lookup); 4500 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
4436 } 4501 }
4437 if (known_global_function) { 4502 if (known_global_function) {
4438 // Push the global object instead of the global receiver because 4503 // Push the global object instead of the global receiver because
4439 // code generated by the full code generator expects it. 4504 // code generated by the full code generator expects it.
4440 HContext* context = new(zone()) HContext; 4505 HValue* context = environment()->LookupContext();
4441 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 4506 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
4442 AddInstruction(context);
4443 PushAndAdd(global_object); 4507 PushAndAdd(global_object);
4444 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4508 CHECK_ALIVE(VisitExpressions(expr->arguments()));
4445 4509
4446 CHECK_ALIVE(VisitForValue(expr->expression())); 4510 CHECK_ALIVE(VisitForValue(expr->expression()));
4447 HValue* function = Pop(); 4511 HValue* function = Pop();
4448 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 4512 AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
4449 4513
4450 // Replace the global object with the global receiver. 4514 // Replace the global object with the global receiver.
4451 HGlobalReceiver* global_receiver = 4515 HGlobalReceiver* global_receiver =
4452 new(zone()) HGlobalReceiver(global_object); 4516 new(zone()) HGlobalReceiver(global_object);
4453 // Index of the receiver from the top of the expression stack. 4517 // Index of the receiver from the top of the expression stack.
4454 const int receiver_index = argument_count - 1; 4518 const int receiver_index = argument_count - 1;
4455 AddInstruction(global_receiver); 4519 AddInstruction(global_receiver);
4456 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 4520 ASSERT(environment()->ExpressionStackAt(receiver_index)->
4457 IsGlobalObject()); 4521 IsGlobalObject());
4458 environment()->SetExpressionStackAt(receiver_index, global_receiver); 4522 environment()->SetExpressionStackAt(receiver_index, global_receiver);
4459 4523
4460 if (TryInline(expr)) return; 4524 if (TryInline(expr)) return;
4461 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 4525 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
4462 argument_count)); 4526 argument_count));
4463 } else { 4527 } else {
4464 HContext* context = new(zone()) HContext; 4528 HValue* context = environment()->LookupContext();
4465 AddInstruction(context);
4466 PushAndAdd(new(zone()) HGlobalObject(context)); 4529 PushAndAdd(new(zone()) HGlobalObject(context));
4467 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4530 CHECK_ALIVE(VisitExpressions(expr->arguments()));
4468 4531
4469 call = PreProcessCall(new(zone()) HCallGlobal(context, 4532 call = PreProcessCall(new(zone()) HCallGlobal(context,
4470 var->name(), 4533 var->name(),
4471 argument_count)); 4534 argument_count));
4472 } 4535 }
4473 4536
4474 } else { 4537 } else {
4475 HContext* context = new(zone()) HContext; 4538 HValue* context = environment()->LookupContext();
4476 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 4539 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
4477 AddInstruction(context);
4478 AddInstruction(global_object); 4540 AddInstruction(global_object);
4479 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); 4541 PushAndAdd(new(zone()) HGlobalReceiver(global_object));
4480 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4542 CHECK_ALIVE(VisitExpressions(expr->arguments()));
4481 4543
4482 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); 4544 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count));
4483 } 4545 }
4484 } 4546 }
4485 4547
4486 call->set_position(expr->position()); 4548 call->set_position(expr->position());
4487 ast_context()->ReturnInstruction(call, expr->id()); 4549 ast_context()->ReturnInstruction(call, expr->id());
4488 } 4550 }
4489 4551
4490 4552
4491 void HGraphBuilder::VisitCallNew(CallNew* expr) { 4553 void HGraphBuilder::VisitCallNew(CallNew* expr) {
4492 ASSERT(!HasStackOverflow()); 4554 ASSERT(!HasStackOverflow());
4493 ASSERT(current_block() != NULL); 4555 ASSERT(current_block() != NULL);
4494 ASSERT(current_block()->HasPredecessor()); 4556 ASSERT(current_block()->HasPredecessor());
4495 // The constructor function is also used as the receiver argument to the 4557 // The constructor function is also used as the receiver argument to the
4496 // JS construct call builtin. 4558 // JS construct call builtin.
4497 CHECK_ALIVE(VisitForValue(expr->expression())); 4559 CHECK_ALIVE(VisitForValue(expr->expression()));
4498 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4560 CHECK_ALIVE(VisitExpressions(expr->arguments()));
4499 4561
4500 HContext* context = new(zone()) HContext; 4562 HValue* context = environment()->LookupContext();
4501 AddInstruction(context);
4502 4563
4503 // The constructor is both an operand to the instruction and an argument 4564 // The constructor is both an operand to the instruction and an argument
4504 // to the construct call. 4565 // to the construct call.
4505 int arg_count = expr->arguments()->length() + 1; // Plus constructor. 4566 int arg_count = expr->arguments()->length() + 1; // Plus constructor.
4506 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); 4567 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1);
4507 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); 4568 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count);
4508 call->set_position(expr->position()); 4569 call->set_position(expr->position());
4509 PreProcessCall(call); 4570 PreProcessCall(call);
4510 ast_context()->ReturnInstruction(call, expr->id()); 4571 ast_context()->ReturnInstruction(call, expr->id());
4511 } 4572 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
4561 Drop(argument_count); 4622 Drop(argument_count);
4562 ast_context()->ReturnInstruction(call, expr->id()); 4623 ast_context()->ReturnInstruction(call, expr->id());
4563 } 4624 }
4564 } 4625 }
4565 4626
4566 4627
4567 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 4628 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4568 ASSERT(!HasStackOverflow()); 4629 ASSERT(!HasStackOverflow());
4569 ASSERT(current_block() != NULL); 4630 ASSERT(current_block() != NULL);
4570 ASSERT(current_block()->HasPredecessor()); 4631 ASSERT(current_block()->HasPredecessor());
4571 Token::Value op = expr->op(); 4632 switch (expr->op()) {
4572 if (op == Token::VOID) { 4633 case Token::DELETE: return VisitDelete(expr);
4634 case Token::VOID: return VisitVoid(expr);
4635 case Token::TYPEOF: return VisitTypeof(expr);
4636 case Token::ADD: return VisitAdd(expr);
4637 case Token::SUB: return VisitSub(expr);
4638 case Token::BIT_NOT: return VisitBitNot(expr);
4639 case Token::NOT: return VisitNot(expr);
4640 default: UNREACHABLE();
4641 }
4642 }
4643
4644 void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
4645 Property* prop = expr->expression()->AsProperty();
4646 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4647 if (prop == NULL && var == NULL) {
4648 // Result of deleting non-property, non-variable reference is true.
4649 // Evaluate the subexpression for side effects.
4573 CHECK_ALIVE(VisitForEffect(expr->expression())); 4650 CHECK_ALIVE(VisitForEffect(expr->expression()));
4574 ast_context()->ReturnValue(graph()->GetConstantUndefined()); 4651 ast_context()->ReturnValue(graph()->GetConstantTrue());
4575 } else if (op == Token::DELETE) { 4652 } else if (var != NULL &&
4576 Property* prop = expr->expression()->AsProperty(); 4653 !var->is_global() &&
4577 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4654 var->AsSlot() != NULL &&
4578 if (prop == NULL && var == NULL) { 4655 var->AsSlot()->type() != Slot::LOOKUP) {
4579 // Result of deleting non-property, non-variable reference is true. 4656 // Result of deleting non-global, non-dynamic variables is false.
4580 // Evaluate the subexpression for side effects. 4657 // The subexpression does not have side effects.
4581 CHECK_ALIVE(VisitForEffect(expr->expression())); 4658 ast_context()->ReturnValue(graph()->GetConstantFalse());
4582 ast_context()->ReturnValue(graph()->GetConstantTrue()); 4659 } else if (prop != NULL) {
4583 } else if (var != NULL && 4660 if (prop->is_synthetic()) {
4584 !var->is_global() && 4661 // Result of deleting parameters is false, even when they rewrite
4585 var->AsSlot() != NULL && 4662 // to accesses on the arguments object.
4586 var->AsSlot()->type() != Slot::LOOKUP) {
4587 // Result of deleting non-global, non-dynamic variables is false.
4588 // The subexpression does not have side effects.
4589 ast_context()->ReturnValue(graph()->GetConstantFalse()); 4663 ast_context()->ReturnValue(graph()->GetConstantFalse());
4590 } else if (prop != NULL) {
4591 if (prop->is_synthetic()) {
4592 // Result of deleting parameters is false, even when they rewrite
4593 // to accesses on the arguments object.
4594 ast_context()->ReturnValue(graph()->GetConstantFalse());
4595 } else {
4596 CHECK_ALIVE(VisitForValue(prop->obj()));
4597 CHECK_ALIVE(VisitForValue(prop->key()));
4598 HValue* key = Pop();
4599 HValue* obj = Pop();
4600 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key);
4601 ast_context()->ReturnInstruction(instr, expr->id());
4602 }
4603 } else if (var->is_global()) {
4604 return Bailout("delete with global variable");
4605 } else { 4664 } else {
4606 return Bailout("delete with non-global variable"); 4665 CHECK_ALIVE(VisitForValue(prop->obj()));
4666 CHECK_ALIVE(VisitForValue(prop->key()));
4667 HValue* key = Pop();
4668 HValue* obj = Pop();
4669 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key);
4670 ast_context()->ReturnInstruction(instr, expr->id());
4607 } 4671 }
4608 } else if (op == Token::NOT) { 4672 } else if (var->is_global()) {
4609 if (ast_context()->IsTest()) { 4673 Bailout("delete with global variable");
4610 TestContext* context = TestContext::cast(ast_context());
4611 VisitForControl(expr->expression(),
4612 context->if_false(),
4613 context->if_true());
4614 } else if (ast_context()->IsValue()) {
4615 HBasicBlock* materialize_false = graph()->CreateBasicBlock();
4616 HBasicBlock* materialize_true = graph()->CreateBasicBlock();
4617 CHECK_BAILOUT(VisitForControl(expr->expression(),
4618 materialize_false,
4619 materialize_true));
4620
4621 if (materialize_false->HasPredecessor()) {
4622 materialize_false->SetJoinId(expr->expression()->id());
4623 set_current_block(materialize_false);
4624 Push(graph()->GetConstantFalse());
4625 } else {
4626 materialize_false = NULL;
4627 }
4628
4629 if (materialize_true->HasPredecessor()) {
4630 materialize_true->SetJoinId(expr->expression()->id());
4631 set_current_block(materialize_true);
4632 Push(graph()->GetConstantTrue());
4633 } else {
4634 materialize_true = NULL;
4635 }
4636
4637 HBasicBlock* join =
4638 CreateJoin(materialize_false, materialize_true, expr->id());
4639 set_current_block(join);
4640 if (join != NULL) ast_context()->ReturnValue(Pop());
4641 } else {
4642 ASSERT(ast_context()->IsEffect());
4643 VisitForEffect(expr->expression());
4644 }
4645
4646 } else if (op == Token::TYPEOF) {
4647 CHECK_ALIVE(VisitForTypeOf(expr->expression()));
4648 HValue* value = Pop();
4649 ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id());
4650
4651 } else { 4674 } else {
4652 CHECK_ALIVE(VisitForValue(expr->expression())); 4675 Bailout("delete with non-global variable");
4653 HValue* value = Pop();
4654 HInstruction* instr = NULL;
4655 switch (op) {
4656 case Token::BIT_NOT:
4657 instr = new(zone()) HBitNot(value);
4658 break;
4659 case Token::SUB:
4660 instr = new(zone()) HMul(value, graph_->GetConstantMinus1());
4661 break;
4662 case Token::ADD:
4663 instr = new(zone()) HMul(value, graph_->GetConstant1());
4664 break;
4665 default:
4666 return Bailout("Value: unsupported unary operation");
4667 break;
4668 }
4669 ast_context()->ReturnInstruction(instr, expr->id());
4670 } 4676 }
4671 } 4677 }
4672 4678
4673 4679
4674 HInstruction* HGraphBuilder::BuildIncrement(HValue* value, 4680 void HGraphBuilder::VisitVoid(UnaryOperation* expr) {
4675 bool increment, 4681 CHECK_ALIVE(VisitForEffect(expr->expression()));
4682 ast_context()->ReturnValue(graph()->GetConstantUndefined());
4683 }
4684
4685
4686 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) {
4687 CHECK_ALIVE(VisitForTypeOf(expr->expression()));
4688 HValue* value = Pop();
4689 ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id());
4690 }
4691
4692
4693 void HGraphBuilder::VisitAdd(UnaryOperation* expr) {
4694 CHECK_ALIVE(VisitForValue(expr->expression()));
4695 HValue* value = Pop();
4696 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1());
4697 ast_context()->ReturnInstruction(instr, expr->id());
4698 }
4699
4700
4701 void HGraphBuilder::VisitSub(UnaryOperation* expr) {
4702 CHECK_ALIVE(VisitForValue(expr->expression()));
4703 HValue* value = Pop();
4704 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1());
4705 TypeInfo info = oracle()->UnaryType(expr);
4706 Representation rep = ToRepresentation(info);
4707 TraceRepresentation(expr->op(), info, instr, rep);
4708 instr->AssumeRepresentation(rep);
4709 ast_context()->ReturnInstruction(instr, expr->id());
4710 }
4711
4712
4713 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
4714 CHECK_ALIVE(VisitForValue(expr->expression()));
4715 HValue* value = Pop();
4716 HInstruction* instr = new(zone()) HBitNot(value);
4717 ast_context()->ReturnInstruction(instr, expr->id());
4718 }
4719
4720
4721 void HGraphBuilder::VisitNot(UnaryOperation* expr) {
4722 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here.
4723 if (ast_context()->IsTest()) {
4724 TestContext* context = TestContext::cast(ast_context());
4725 VisitForControl(expr->expression(),
4726 context->if_false(),
4727 context->if_true());
4728 return;
4729 }
4730
4731 if (ast_context()->IsEffect()) {
4732 VisitForEffect(expr->expression());
4733 return;
4734 }
4735
4736 ASSERT(ast_context()->IsValue());
4737 HBasicBlock* materialize_false = graph()->CreateBasicBlock();
4738 HBasicBlock* materialize_true = graph()->CreateBasicBlock();
4739 CHECK_BAILOUT(VisitForControl(expr->expression(),
4740 materialize_false,
4741 materialize_true));
4742
4743 if (materialize_false->HasPredecessor()) {
4744 materialize_false->SetJoinId(expr->expression()->id());
4745 set_current_block(materialize_false);
4746 Push(graph()->GetConstantFalse());
4747 } else {
4748 materialize_false = NULL;
4749 }
4750
4751 if (materialize_true->HasPredecessor()) {
4752 materialize_true->SetJoinId(expr->expression()->id());
4753 set_current_block(materialize_true);
4754 Push(graph()->GetConstantTrue());
4755 } else {
4756 materialize_true = NULL;
4757 }
4758
4759 HBasicBlock* join =
4760 CreateJoin(materialize_false, materialize_true, expr->id());
4761 set_current_block(join);
4762 if (join != NULL) ast_context()->ReturnValue(Pop());
4763 }
4764
4765
4766 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input,
4676 CountOperation* expr) { 4767 CountOperation* expr) {
4677 HConstant* delta = increment 4768 // The input to the count operation is on top of the expression stack.
4678 ? graph_->GetConstant1() 4769 TypeInfo info = oracle()->IncrementType(expr);
4679 : graph_->GetConstantMinus1(); 4770 Representation rep = ToRepresentation(info);
4680 HInstruction* instr = new(zone()) HAdd(value, delta);
4681 Representation rep = ToRepresentation(oracle()->IncrementType(expr));
4682 if (rep.IsTagged()) { 4771 if (rep.IsTagged()) {
4683 rep = Representation::Integer32(); 4772 rep = Representation::Integer32();
4684 } 4773 }
4685 AssumeRepresentation(instr, rep); 4774
4775 if (returns_original_input) {
4776 // We need an explicit HValue representing ToNumber(input). The
4777 // actual HChange instruction we need is (sometimes) added in a later
4778 // phase, so it is not available now to be used as an input to HAdd and
4779 // as the return value.
4780 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep);
4781 AddInstruction(number_input);
4782 Push(number_input);
4783 }
4784
4785 // The addition has no side effects, so we do not need
4786 // to simulate the expression stack after this instruction.
4787 // Any later failures deopt to the load of the input or earlier.
4788 HConstant* delta = (expr->op() == Token::INC)
4789 ? graph_->GetConstant1()
4790 : graph_->GetConstantMinus1();
4791 HInstruction* instr = new(zone()) HAdd(Top(), delta);
4792 TraceRepresentation(expr->op(), info, instr, rep);
4793 instr->AssumeRepresentation(rep);
4794 AddInstruction(instr);
4686 return instr; 4795 return instr;
4687 } 4796 }
4688 4797
4689 4798
4690 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { 4799 void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4691 ASSERT(!HasStackOverflow()); 4800 ASSERT(!HasStackOverflow());
4692 ASSERT(current_block() != NULL); 4801 ASSERT(current_block() != NULL);
4693 ASSERT(current_block()->HasPredecessor()); 4802 ASSERT(current_block()->HasPredecessor());
4694 Expression* target = expr->expression(); 4803 Expression* target = expr->expression();
4695 VariableProxy* proxy = target->AsVariableProxy(); 4804 VariableProxy* proxy = target->AsVariableProxy();
4696 Variable* var = proxy->AsVariable(); 4805 Variable* var = proxy->AsVariable();
4697 Property* prop = target->AsProperty(); 4806 Property* prop = target->AsProperty();
4698 ASSERT(var == NULL || prop == NULL); 4807 if (var == NULL && prop == NULL) {
4699 bool inc = expr->op() == Token::INC; 4808 return Bailout("invalid lhs in count operation");
4809 }
4810
4811 // Match the full code generator stack by simulating an extra stack
4812 // element for postfix operations in a non-effect context. The return
4813 // value is ToNumber(input).
4814 bool returns_original_input =
4815 expr->is_postfix() && !ast_context()->IsEffect();
4816 HValue* input = NULL; // ToNumber(original_input).
4817 HValue* after = NULL; // The result after incrementing or decrementing.
4700 4818
4701 if (var != NULL) { 4819 if (var != NULL) {
4820 // Argument of the count operation is a variable, not a property.
4821 ASSERT(prop == NULL);
4702 CHECK_ALIVE(VisitForValue(target)); 4822 CHECK_ALIVE(VisitForValue(target));
4703 4823
4704 // Match the full code generator stack by simulating an extra stack 4824 after = BuildIncrement(returns_original_input, expr);
4705 // element for postfix operations in a non-effect context. 4825 input = returns_original_input ? Top() : Pop();
4706 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4707 HValue* before = has_extra ? Top() : Pop();
4708 HInstruction* after = BuildIncrement(before, inc, expr);
4709 AddInstruction(after);
4710 Push(after); 4826 Push(after);
4711 4827
4712 if (var->is_global()) { 4828 if (var->is_global()) {
4713 HandleGlobalVariableAssignment(var, 4829 HandleGlobalVariableAssignment(var,
4714 after, 4830 after,
4715 expr->position(), 4831 expr->position(),
4716 expr->AssignmentId()); 4832 expr->AssignmentId());
4717 } else if (var->IsStackAllocated()) { 4833 } else if (var->IsStackAllocated()) {
4718 Bind(var, after); 4834 Bind(var, after);
4719 } else if (var->IsContextSlot()) { 4835 } else if (var->IsContextSlot()) {
4720 HValue* context = BuildContextChainWalk(var); 4836 HValue* context = BuildContextChainWalk(var);
4721 int index = var->AsSlot()->index(); 4837 int index = var->AsSlot()->index();
4722 HStoreContextSlot* instr = 4838 HStoreContextSlot* instr =
4723 new(zone()) HStoreContextSlot(context, index, after); 4839 new(zone()) HStoreContextSlot(context, index, after);
4724 AddInstruction(instr); 4840 AddInstruction(instr);
4725 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4841 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
4726 } else { 4842 } else {
4727 return Bailout("lookup variable in count operation"); 4843 return Bailout("lookup variable in count operation");
4728 } 4844 }
4729 Drop(has_extra ? 2 : 1);
4730 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4731 4845
4732 } else if (prop != NULL) { 4846 } else {
4847 // Argument of the count operation is a property.
4848 ASSERT(prop != NULL);
4733 prop->RecordTypeFeedback(oracle()); 4849 prop->RecordTypeFeedback(oracle());
4734 4850
4735 if (prop->key()->IsPropertyName()) { 4851 if (prop->key()->IsPropertyName()) {
4736 // Named property. 4852 // Named property.
4737 4853 if (returns_original_input) Push(graph_->GetConstantUndefined());
4738 // Match the full code generator stack by simulating an extra stack
4739 // element for postfix operations in a non-effect context.
4740 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4741 if (has_extra) Push(graph_->GetConstantUndefined());
4742 4854
4743 CHECK_ALIVE(VisitForValue(prop->obj())); 4855 CHECK_ALIVE(VisitForValue(prop->obj()));
4744 HValue* obj = Top(); 4856 HValue* obj = Top();
4745 4857
4746 HInstruction* load = NULL; 4858 HInstruction* load = NULL;
4747 if (prop->IsMonomorphic()) { 4859 if (prop->IsMonomorphic()) {
4748 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4860 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4749 Handle<Map> map = prop->GetReceiverTypes()->first(); 4861 Handle<Map> map = prop->GetReceiverTypes()->first();
4750 load = BuildLoadNamed(obj, prop, map, name); 4862 load = BuildLoadNamed(obj, prop, map, name);
4751 } else { 4863 } else {
4752 load = BuildLoadNamedGeneric(obj, prop); 4864 load = BuildLoadNamedGeneric(obj, prop);
4753 } 4865 }
4754 PushAndAdd(load); 4866 PushAndAdd(load);
4755 if (load->HasSideEffects()) AddSimulate(expr->CountId()); 4867 if (load->HasSideEffects()) AddSimulate(expr->CountId());
4756 4868
4757 HValue* before = Pop(); 4869 after = BuildIncrement(returns_original_input, expr);
4758 // There is no deoptimization to after the increment, so we don't need 4870 input = Pop();
4759 // to simulate the expression stack after this instruction.
4760 HInstruction* after = BuildIncrement(before, inc, expr);
4761 AddInstruction(after);
4762 4871
4763 HInstruction* store = BuildStoreNamed(obj, after, prop); 4872 HInstruction* store = BuildStoreNamed(obj, after, prop);
4764 AddInstruction(store); 4873 AddInstruction(store);
4765 4874
4766 // Overwrite the receiver in the bailout environment with the result 4875 // Overwrite the receiver in the bailout environment with the result
4767 // of the operation, and the placeholder with the original value if 4876 // of the operation, and the placeholder with the original value if
4768 // necessary. 4877 // necessary.
4769 environment()->SetExpressionStackAt(0, after); 4878 environment()->SetExpressionStackAt(0, after);
4770 if (has_extra) environment()->SetExpressionStackAt(1, before); 4879 if (returns_original_input) environment()->SetExpressionStackAt(1, input);
4771 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4880 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4772 Drop(has_extra ? 2 : 1);
4773
4774 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4775 4881
4776 } else { 4882 } else {
4777 // Keyed property. 4883 // Keyed property.
4778 4884 if (returns_original_input) Push(graph_->GetConstantUndefined());
4779 // Match the full code generator stack by simulate an extra stack element
4780 // for postfix operations in a non-effect context.
4781 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4782 if (has_extra) Push(graph_->GetConstantUndefined());
4783 4885
4784 CHECK_ALIVE(VisitForValue(prop->obj())); 4886 CHECK_ALIVE(VisitForValue(prop->obj()));
4785 CHECK_ALIVE(VisitForValue(prop->key())); 4887 CHECK_ALIVE(VisitForValue(prop->key()));
4786 HValue* obj = environment()->ExpressionStackAt(1); 4888 HValue* obj = environment()->ExpressionStackAt(1);
4787 HValue* key = environment()->ExpressionStackAt(0); 4889 HValue* key = environment()->ExpressionStackAt(0);
4788 4890
4789 HInstruction* load = BuildLoadKeyed(obj, key, prop); 4891 HInstruction* load = BuildLoadKeyed(obj, key, prop);
4790 PushAndAdd(load); 4892 PushAndAdd(load);
4791 if (load->HasSideEffects()) AddSimulate(expr->CountId()); 4893 if (load->HasSideEffects()) AddSimulate(expr->CountId());
4792 4894
4793 HValue* before = Pop(); 4895 after = BuildIncrement(returns_original_input, expr);
4794 // There is no deoptimization to after the increment, so we don't need 4896 input = Pop();
4795 // to simulate the expression stack after this instruction.
4796 HInstruction* after = BuildIncrement(before, inc, expr);
4797 AddInstruction(after);
4798 4897
4799 expr->RecordTypeFeedback(oracle()); 4898 expr->RecordTypeFeedback(oracle());
4800 HInstruction* store = BuildStoreKeyed(obj, key, after, expr); 4899 HInstruction* store = BuildStoreKeyed(obj, key, after, expr);
4801 AddInstruction(store); 4900 AddInstruction(store);
4802 4901
4803 // Drop the key from the bailout environment. Overwrite the receiver 4902 // Drop the key from the bailout environment. Overwrite the receiver
4804 // with the result of the operation, and the placeholder with the 4903 // with the result of the operation, and the placeholder with the
4805 // original value if necessary. 4904 // original value if necessary.
4806 Drop(1); 4905 Drop(1);
4807 environment()->SetExpressionStackAt(0, after); 4906 environment()->SetExpressionStackAt(0, after);
4808 if (has_extra) environment()->SetExpressionStackAt(1, before); 4907 if (returns_original_input) environment()->SetExpressionStackAt(1, input);
4809 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4908 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4810 Drop(has_extra ? 2 : 1); 4909 }
4910 }
4811 4911
4812 ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4912 Drop(returns_original_input ? 2 : 1);
4813 } 4913 ast_context()->ReturnValue(expr->is_postfix() ? input : after);
4914 }
4814 4915
4815 } else { 4916
4816 return Bailout("invalid lhs in count operation"); 4917 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left,
4817 } 4918 HValue* right,
4919 Token::Value op) {
4920 ASSERT(op == Token::EQ || op == Token::EQ_STRICT);
4921 AddInstruction(new(zone()) HCheckNonSmi(left));
4922 AddInstruction(HCheckInstanceType::NewIsSymbol(left));
4923 AddInstruction(new(zone()) HCheckNonSmi(right));
4924 AddInstruction(HCheckInstanceType::NewIsSymbol(right));
4925 return new(zone()) HCompareSymbolEq(left, right, op);
4818 } 4926 }
4819 4927
4820 4928
4821 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, 4929 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string,
4822 HValue* index) { 4930 HValue* index) {
4823 AddInstruction(new(zone()) HCheckNonSmi(string)); 4931 AddInstruction(new(zone()) HCheckNonSmi(string));
4824 AddInstruction(new(zone()) HCheckInstanceType( 4932 AddInstruction(HCheckInstanceType::NewIsString(string));
4825 string, FIRST_STRING_TYPE, LAST_STRING_TYPE));
4826 HStringLength* length = new(zone()) HStringLength(string); 4933 HStringLength* length = new(zone()) HStringLength(string);
4827 AddInstruction(length); 4934 AddInstruction(length);
4828 AddInstruction(new(zone()) HBoundsCheck(index, length)); 4935 AddInstruction(new(zone()) HBoundsCheck(index, length));
4829 return new(zone()) HStringCharCodeAt(string, index); 4936 return new(zone()) HStringCharCodeAt(string, index);
4830 } 4937 }
4831 4938
4832 4939
4833 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 4940 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4834 HValue* left, 4941 HValue* left,
4835 HValue* right) { 4942 HValue* right) {
4836 TypeInfo info = oracle()->BinaryType(expr); 4943 TypeInfo info = oracle()->BinaryType(expr);
4837 HInstruction* instr = NULL; 4944 HInstruction* instr = BuildBinaryOperation(expr->op(), left, right, info);
4838 switch (expr->op()) {
4839 case Token::ADD:
4840 if (info.IsString()) {
4841 AddInstruction(new(zone()) HCheckNonSmi(left));
4842 AddInstruction(new(zone()) HCheckInstanceType(
4843 left, FIRST_STRING_TYPE, LAST_STRING_TYPE));
4844 AddInstruction(new(zone()) HCheckNonSmi(right));
4845 AddInstruction(new(zone()) HCheckInstanceType(
4846 right, FIRST_STRING_TYPE, LAST_STRING_TYPE));
4847 instr = new(zone()) HStringAdd(left, right);
4848 } else {
4849 instr = new(zone()) HAdd(left, right);
4850 }
4851 break;
4852 case Token::SUB:
4853 instr = new(zone()) HSub(left, right);
4854 break;
4855 case Token::MUL:
4856 instr = new(zone()) HMul(left, right);
4857 break;
4858 case Token::MOD:
4859 instr = new(zone()) HMod(left, right);
4860 break;
4861 case Token::DIV:
4862 instr = new(zone()) HDiv(left, right);
4863 break;
4864 case Token::BIT_XOR:
4865 instr = new(zone()) HBitXor(left, right);
4866 break;
4867 case Token::BIT_AND:
4868 instr = new(zone()) HBitAnd(left, right);
4869 break;
4870 case Token::BIT_OR:
4871 instr = new(zone()) HBitOr(left, right);
4872 break;
4873 case Token::SAR:
4874 instr = new(zone()) HSar(left, right);
4875 break;
4876 case Token::SHR:
4877 instr = new(zone()) HShr(left, right);
4878 break;
4879 case Token::SHL:
4880 instr = new(zone()) HShl(left, right);
4881 break;
4882 default:
4883 UNREACHABLE();
4884 }
4885 // If we hit an uninitialized binary op stub we will get type info 4945 // If we hit an uninitialized binary op stub we will get type info
4886 // for a smi operation. If one of the operands is a constant string 4946 // for a smi operation. If one of the operands is a constant string
4887 // do not generate code assuming it is a smi operation. 4947 // do not generate code assuming it is a smi operation.
4888 if (info.IsSmi() && 4948 if (info.IsSmi() &&
4889 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 4949 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
4890 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 4950 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
4891 return instr; 4951 return instr;
4892 } 4952 }
4893 if (FLAG_trace_representation) {
4894 PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic());
4895 }
4896 Representation rep = ToRepresentation(info); 4953 Representation rep = ToRepresentation(info);
4897 // We only generate either int32 or generic tagged bitwise operations. 4954 // We only generate either int32 or generic tagged bitwise operations.
4898 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) { 4955 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
4899 rep = Representation::Integer32(); 4956 rep = Representation::Integer32();
4900 } 4957 }
4901 AssumeRepresentation(instr, rep); 4958 TraceRepresentation(expr->op(), info, instr, rep);
4959 instr->AssumeRepresentation(rep);
4902 return instr; 4960 return instr;
4903 } 4961 }
4904 4962
4905 4963
4964 HInstruction* HGraphBuilder::BuildBinaryOperation(
4965 Token::Value op, HValue* left, HValue* right, TypeInfo info) {
4966 switch (op) {
4967 case Token::ADD:
4968 if (info.IsString()) {
4969 AddInstruction(new(zone()) HCheckNonSmi(left));
4970 AddInstruction(HCheckInstanceType::NewIsString(left));
4971 AddInstruction(new(zone()) HCheckNonSmi(right));
4972 AddInstruction(HCheckInstanceType::NewIsString(right));
4973 return new(zone()) HStringAdd(left, right);
4974 } else {
4975 return new(zone()) HAdd(left, right);
4976 }
4977 case Token::SUB: return new(zone()) HSub(left, right);
4978 case Token::MUL: return new(zone()) HMul(left, right);
4979 case Token::MOD: return new(zone()) HMod(left, right);
4980 case Token::DIV: return new(zone()) HDiv(left, right);
4981 case Token::BIT_XOR: return new(zone()) HBitXor(left, right);
4982 case Token::BIT_AND: return new(zone()) HBitAnd(left, right);
4983 case Token::BIT_OR: return new(zone()) HBitOr(left, right);
4984 case Token::SAR: return new(zone()) HSar(left, right);
4985 case Token::SHR: return new(zone()) HShr(left, right);
4986 case Token::SHL: return new(zone()) HShl(left, right);
4987 default:
4988 UNREACHABLE();
4989 return NULL;
4990 }
4991 }
4992
4993
4906 // Check for the form (%_ClassOf(foo) === 'BarClass'). 4994 // Check for the form (%_ClassOf(foo) === 'BarClass').
4907 static bool IsClassOfTest(CompareOperation* expr) { 4995 static bool IsClassOfTest(CompareOperation* expr) {
4908 if (expr->op() != Token::EQ_STRICT) return false; 4996 if (expr->op() != Token::EQ_STRICT) return false;
4909 CallRuntime* call = expr->left()->AsCallRuntime(); 4997 CallRuntime* call = expr->left()->AsCallRuntime();
4910 if (call == NULL) return false; 4998 if (call == NULL) return false;
4911 Literal* literal = expr->right()->AsLiteral(); 4999 Literal* literal = expr->right()->AsLiteral();
4912 if (literal == NULL) return false; 5000 if (literal == NULL) return false;
4913 if (!literal->handle()->IsString()) return false; 5001 if (!literal->handle()->IsString()) return false;
4914 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 5002 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
4915 ASSERT(call->arguments()->length() == 1); 5003 ASSERT(call->arguments()->length() == 1);
4916 return true; 5004 return true;
4917 } 5005 }
4918 5006
4919 5007
4920 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 5008 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
4921 ASSERT(!HasStackOverflow()); 5009 ASSERT(!HasStackOverflow());
4922 ASSERT(current_block() != NULL); 5010 ASSERT(current_block() != NULL);
4923 ASSERT(current_block()->HasPredecessor()); 5011 ASSERT(current_block()->HasPredecessor());
4924 if (expr->op() == Token::COMMA) { 5012 switch (expr->op()) {
4925 CHECK_ALIVE(VisitForEffect(expr->left())); 5013 case Token::COMMA: return VisitComma(expr);
4926 // Visit the right subexpression in the same AST context as the entire 5014 case Token::OR: return VisitAndOr(expr, false);
4927 // expression. 5015 case Token::AND: return VisitAndOr(expr, true);
4928 Visit(expr->right()); 5016 default: return VisitCommon(expr);
4929
4930 } else if (expr->op() == Token::AND || expr->op() == Token::OR) {
4931 bool is_logical_and = (expr->op() == Token::AND);
4932 if (ast_context()->IsTest()) {
4933 TestContext* context = TestContext::cast(ast_context());
4934 // Translate left subexpression.
4935 HBasicBlock* eval_right = graph()->CreateBasicBlock();
4936 if (is_logical_and) {
4937 CHECK_BAILOUT(VisitForControl(expr->left(),
4938 eval_right,
4939 context->if_false()));
4940 } else {
4941 CHECK_BAILOUT(VisitForControl(expr->left(),
4942 context->if_true(),
4943 eval_right));
4944 }
4945
4946 // Translate right subexpression by visiting it in the same AST
4947 // context as the entire expression.
4948 if (eval_right->HasPredecessor()) {
4949 eval_right->SetJoinId(expr->RightId());
4950 set_current_block(eval_right);
4951 Visit(expr->right());
4952 }
4953
4954 } else if (ast_context()->IsValue()) {
4955 CHECK_ALIVE(VisitForValue(expr->left()));
4956 ASSERT(current_block() != NULL);
4957
4958 // We need an extra block to maintain edge-split form.
4959 HBasicBlock* empty_block = graph()->CreateBasicBlock();
4960 HBasicBlock* eval_right = graph()->CreateBasicBlock();
4961 HTest* test = is_logical_and
4962 ? new(zone()) HTest(Top(), eval_right, empty_block)
4963 : new(zone()) HTest(Top(), empty_block, eval_right);
4964 current_block()->Finish(test);
4965
4966 set_current_block(eval_right);
4967 Drop(1); // Value of the left subexpression.
4968 CHECK_BAILOUT(VisitForValue(expr->right()));
4969
4970 HBasicBlock* join_block =
4971 CreateJoin(empty_block, current_block(), expr->id());
4972 set_current_block(join_block);
4973 ast_context()->ReturnValue(Pop());
4974
4975 } else {
4976 ASSERT(ast_context()->IsEffect());
4977 // In an effect context, we don't need the value of the left
4978 // subexpression, only its control flow and side effects. We need an
4979 // extra block to maintain edge-split form.
4980 HBasicBlock* empty_block = graph()->CreateBasicBlock();
4981 HBasicBlock* right_block = graph()->CreateBasicBlock();
4982 if (is_logical_and) {
4983 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
4984 } else {
4985 CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
4986 }
4987
4988 // TODO(kmillikin): Find a way to fix this. It's ugly that there are
4989 // actually two empty blocks (one here and one inserted by
4990 // TestContext::BuildBranch, and that they both have an HSimulate
4991 // though the second one is not a merge node, and that we really have
4992 // no good AST ID to put on that first HSimulate.
4993 if (empty_block->HasPredecessor()) {
4994 empty_block->SetJoinId(expr->id());
4995 } else {
4996 empty_block = NULL;
4997 }
4998
4999 if (right_block->HasPredecessor()) {
5000 right_block->SetJoinId(expr->RightId());
5001 set_current_block(right_block);
5002 CHECK_BAILOUT(VisitForEffect(expr->right()));
5003 right_block = current_block();
5004 } else {
5005 right_block = NULL;
5006 }
5007
5008 HBasicBlock* join_block =
5009 CreateJoin(empty_block, right_block, expr->id());
5010 set_current_block(join_block);
5011 // We did not materialize any value in the predecessor environments,
5012 // so there is no need to handle it here.
5013 }
5014
5015 } else {
5016 CHECK_ALIVE(VisitForValue(expr->left()));
5017 CHECK_ALIVE(VisitForValue(expr->right()));
5018
5019 HValue* right = Pop();
5020 HValue* left = Pop();
5021 HInstruction* instr = BuildBinaryOperation(expr, left, right);
5022 instr->set_position(expr->position());
5023 ast_context()->ReturnInstruction(instr, expr->id());
5024 } 5017 }
5025 } 5018 }
5026 5019
5027 5020
5028 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) { 5021 void HGraphBuilder::VisitComma(BinaryOperation* expr) {
5029 if (value->CheckFlag(HValue::kFlexibleRepresentation)) { 5022 CHECK_ALIVE(VisitForEffect(expr->left()));
5030 if (FLAG_trace_representation) { 5023 // Visit the right subexpression in the same AST context as the entire
5031 PrintF("Assume representation for %s to be %s (%d)\n", 5024 // expression.
5032 value->Mnemonic(), 5025 Visit(expr->right());
5033 r.Mnemonic(), 5026 }
5034 graph_->GetMaximumValueID()); 5027
5028
5029 void HGraphBuilder::VisitAndOr(BinaryOperation* expr, bool is_logical_and) {
5030 if (ast_context()->IsTest()) {
5031 TestContext* context = TestContext::cast(ast_context());
5032 // Translate left subexpression.
5033 HBasicBlock* eval_right = graph()->CreateBasicBlock();
5034 if (is_logical_and) {
5035 CHECK_BAILOUT(VisitForControl(expr->left(),
5036 eval_right,
5037 context->if_false()));
5038 } else {
5039 CHECK_BAILOUT(VisitForControl(expr->left(),
5040 context->if_true(),
5041 eval_right));
5035 } 5042 }
5036 value->ChangeRepresentation(r); 5043
5037 // The representation of the value is dictated by type feedback and 5044 // Translate right subexpression by visiting it in the same AST
5038 // will not be changed later. 5045 // context as the entire expression.
5039 value->ClearFlag(HValue::kFlexibleRepresentation); 5046 if (eval_right->HasPredecessor()) {
5040 } else if (FLAG_trace_representation) { 5047 eval_right->SetJoinId(expr->RightId());
5041 PrintF("No representation assumed\n"); 5048 set_current_block(eval_right);
5049 Visit(expr->right());
5050 }
5051
5052 } else if (ast_context()->IsValue()) {
5053 CHECK_ALIVE(VisitForValue(expr->left()));
5054 ASSERT(current_block() != NULL);
5055
5056 // We need an extra block to maintain edge-split form.
5057 HBasicBlock* empty_block = graph()->CreateBasicBlock();
5058 HBasicBlock* eval_right = graph()->CreateBasicBlock();
5059 HTest* test = is_logical_and
5060 ? new(zone()) HTest(Top(), eval_right, empty_block)
5061 : new(zone()) HTest(Top(), empty_block, eval_right);
5062 current_block()->Finish(test);
5063
5064 set_current_block(eval_right);
5065 Drop(1); // Value of the left subexpression.
5066 CHECK_BAILOUT(VisitForValue(expr->right()));
5067
5068 HBasicBlock* join_block =
5069 CreateJoin(empty_block, current_block(), expr->id());
5070 set_current_block(join_block);
5071 ast_context()->ReturnValue(Pop());
5072
5073 } else {
5074 ASSERT(ast_context()->IsEffect());
5075 // In an effect context, we don't need the value of the left subexpression,
5076 // only its control flow and side effects. We need an extra block to
5077 // maintain edge-split form.
5078 HBasicBlock* empty_block = graph()->CreateBasicBlock();
5079 HBasicBlock* right_block = graph()->CreateBasicBlock();
5080 if (is_logical_and) {
5081 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
5082 } else {
5083 CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
5084 }
5085
5086 // TODO(kmillikin): Find a way to fix this. It's ugly that there are
5087 // actually two empty blocks (one here and one inserted by
5088 // TestContext::BuildBranch, and that they both have an HSimulate though the
5089 // second one is not a merge node, and that we really have no good AST ID to
5090 // put on that first HSimulate.
5091
5092 if (empty_block->HasPredecessor()) {
5093 empty_block->SetJoinId(expr->id());
5094 } else {
5095 empty_block = NULL;
5096 }
5097
5098 if (right_block->HasPredecessor()) {
5099 right_block->SetJoinId(expr->RightId());
5100 set_current_block(right_block);
5101 CHECK_BAILOUT(VisitForEffect(expr->right()));
5102 right_block = current_block();
5103 } else {
5104 right_block = NULL;
5105 }
5106
5107 HBasicBlock* join_block =
5108 CreateJoin(empty_block, right_block, expr->id());
5109 set_current_block(join_block);
5110 // We did not materialize any value in the predecessor environments,
5111 // so there is no need to handle it here.
5042 } 5112 }
5043 } 5113 }
5044 5114
5045 5115
5116 void HGraphBuilder::VisitCommon(BinaryOperation* expr) {
5117 CHECK_ALIVE(VisitForValue(expr->left()));
5118 CHECK_ALIVE(VisitForValue(expr->right()));
5119 HValue* right = Pop();
5120 HValue* left = Pop();
5121 HInstruction* instr = BuildBinaryOperation(expr, left, right);
5122 instr->set_position(expr->position());
5123 ast_context()->ReturnInstruction(instr, expr->id());
5124 }
5125
5126
5127 void HGraphBuilder::TraceRepresentation(Token::Value op,
5128 TypeInfo info,
5129 HValue* value,
5130 Representation rep) {
5131 if (!FLAG_trace_representation) return;
5132 // TODO(svenpanne) Under which circumstances are we actually not flexible?
5133 // At first glance, this looks a bit weird...
5134 bool flexible = value->CheckFlag(HValue::kFlexibleRepresentation);
5135 PrintF("Operation %s has type info %s, %schange representation assumption "
5136 "for %s (ID %d) from %s to %s\n",
5137 Token::Name(op),
5138 info.ToString(),
5139 flexible ? "" : " DO NOT ",
5140 value->Mnemonic(),
5141 graph_->GetMaximumValueID(),
5142 value->representation().Mnemonic(),
5143 rep.Mnemonic());
5144 }
5145
5146
5046 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { 5147 Representation HGraphBuilder::ToRepresentation(TypeInfo info) {
5047 if (info.IsSmi()) return Representation::Integer32(); 5148 if (info.IsSmi()) return Representation::Integer32();
5048 if (info.IsInteger32()) return Representation::Integer32(); 5149 if (info.IsInteger32()) return Representation::Integer32();
5049 if (info.IsDouble()) return Representation::Double(); 5150 if (info.IsDouble()) return Representation::Double();
5050 if (info.IsNumber()) return Representation::Double(); 5151 if (info.IsNumber()) return Representation::Double();
5051 return Representation::Tagged(); 5152 return Representation::Tagged();
5052 } 5153 }
5053 5154
5054 5155
5055 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 5156 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
5114 // change and thus prefer the general IC code. 5215 // change and thus prefer the general IC code.
5115 if (!isolate()->heap()->InNewSpace(*candidate)) { 5216 if (!isolate()->heap()->InNewSpace(*candidate)) {
5116 target = candidate; 5217 target = candidate;
5117 } 5218 }
5118 } 5219 }
5119 } 5220 }
5120 5221
5121 // If the target is not null we have found a known global function that is 5222 // If the target is not null we have found a known global function that is
5122 // assumed to stay the same for this instanceof. 5223 // assumed to stay the same for this instanceof.
5123 if (target.is_null()) { 5224 if (target.is_null()) {
5124 HContext* context = new(zone()) HContext; 5225 HValue* context = environment()->LookupContext();
5125 AddInstruction(context);
5126 instr = new(zone()) HInstanceOf(context, left, right); 5226 instr = new(zone()) HInstanceOf(context, left, right);
5127 } else { 5227 } else {
5128 AddInstruction(new(zone()) HCheckFunction(right, target)); 5228 AddInstruction(new(zone()) HCheckFunction(right, target));
5129 instr = new(zone()) HInstanceOfKnownGlobal(left, target); 5229 instr = new(zone()) HInstanceOfKnownGlobal(left, target);
5130 } 5230 }
5131 } else if (op == Token::IN) { 5231 } else if (op == Token::IN) {
5132 instr = new(zone()) HIn(left, right); 5232 instr = new(zone()) HIn(left, right);
5133 } else if (type_info.IsNonPrimitive()) { 5233 } else if (type_info.IsNonPrimitive()) {
5134 switch (op) { 5234 switch (op) {
5135 case Token::EQ: 5235 case Token::EQ:
5136 case Token::EQ_STRICT: { 5236 case Token::EQ_STRICT: {
5137 AddInstruction(new(zone()) HCheckNonSmi(left)); 5237 AddInstruction(new(zone()) HCheckNonSmi(left));
5138 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); 5238 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left));
5139 AddInstruction(new(zone()) HCheckNonSmi(right)); 5239 AddInstruction(new(zone()) HCheckNonSmi(right));
5140 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); 5240 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right));
5141 instr = new(zone()) HCompareJSObjectEq(left, right); 5241 instr = new(zone()) HCompareJSObjectEq(left, right);
5142 break; 5242 break;
5143 } 5243 }
5144 default: 5244 default:
5145 return Bailout("Unsupported non-primitive compare"); 5245 return Bailout("Unsupported non-primitive compare");
5146 break; 5246 break;
5147 } 5247 }
5248 } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) &&
5249 (op == Token::EQ || op == Token::EQ_STRICT)) {
5250 instr = BuildSymbolCompare(left, right, op);
5148 } else { 5251 } else {
5149 HCompare* compare = new(zone()) HCompare(left, right, op); 5252 HCompare* compare = new(zone()) HCompare(left, right, op);
5150 Representation r = ToRepresentation(type_info); 5253 Representation r = ToRepresentation(type_info);
5151 compare->SetInputRepresentation(r); 5254 compare->SetInputRepresentation(r);
5152 instr = compare; 5255 instr = compare;
5153 } 5256 }
5154 instr->set_position(expr->position()); 5257 instr->set_position(expr->position());
5155 ast_context()->ReturnInstruction(instr, expr->id()); 5258 ast_context()->ReturnInstruction(instr, expr->id());
5156 } 5259 }
5157 5260
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
5259 ast_context()->ReturnInstruction(test, call->id()); 5362 ast_context()->ReturnInstruction(test, call->id());
5260 } 5363 }
5261 5364
5262 5365
5263 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { 5366 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
5264 return Bailout("inlined runtime function: IsNonNegativeSmi"); 5367 return Bailout("inlined runtime function: IsNonNegativeSmi");
5265 } 5368 }
5266 5369
5267 5370
5268 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { 5371 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
5269 return Bailout("inlined runtime function: IsUndetectableObject"); 5372 ASSERT(call->arguments()->length() == 1);
5373 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5374 HValue* value = Pop();
5375 ast_context()->ReturnInstruction(new(zone()) HIsUndetectable(value),
5376 call->id());
5270 } 5377 }
5271 5378
5272 5379
5273 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 5380 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
5274 CallRuntime* call) { 5381 CallRuntime* call) {
5275 return Bailout( 5382 return Bailout(
5276 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 5383 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
5277 } 5384 }
5278 5385
5279 5386
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
5391 // Fast support for Math.random(). 5498 // Fast support for Math.random().
5392 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { 5499 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
5393 return Bailout("inlined runtime function: RandomHeapNumber"); 5500 return Bailout("inlined runtime function: RandomHeapNumber");
5394 } 5501 }
5395 5502
5396 5503
5397 // Fast support for StringAdd. 5504 // Fast support for StringAdd.
5398 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { 5505 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
5399 ASSERT_EQ(2, call->arguments()->length()); 5506 ASSERT_EQ(2, call->arguments()->length());
5400 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5507 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5401 HContext* context = new(zone()) HContext; 5508 HValue* context = environment()->LookupContext();
5402 AddInstruction(context);
5403 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); 5509 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2);
5404 Drop(2); 5510 Drop(2);
5405 ast_context()->ReturnInstruction(result, call->id()); 5511 ast_context()->ReturnInstruction(result, call->id());
5406 } 5512 }
5407 5513
5408 5514
5409 // Fast support for SubString. 5515 // Fast support for SubString.
5410 void HGraphBuilder::GenerateSubString(CallRuntime* call) { 5516 void HGraphBuilder::GenerateSubString(CallRuntime* call) {
5411 ASSERT_EQ(3, call->arguments()->length()); 5517 ASSERT_EQ(3, call->arguments()->length());
5412 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5518 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5413 HContext* context = new(zone()) HContext; 5519 HValue* context = environment()->LookupContext();
5414 AddInstruction(context);
5415 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); 5520 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3);
5416 Drop(3); 5521 Drop(3);
5417 ast_context()->ReturnInstruction(result, call->id()); 5522 ast_context()->ReturnInstruction(result, call->id());
5418 } 5523 }
5419 5524
5420 5525
5421 // Fast support for StringCompare. 5526 // Fast support for StringCompare.
5422 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { 5527 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
5423 ASSERT_EQ(2, call->arguments()->length()); 5528 ASSERT_EQ(2, call->arguments()->length());
5424 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5529 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5425 HContext* context = new(zone()) HContext; 5530 HValue* context = environment()->LookupContext();
5426 AddInstruction(context);
5427 HCallStub* result = 5531 HCallStub* result =
5428 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); 5532 new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
5429 Drop(2); 5533 Drop(2);
5430 ast_context()->ReturnInstruction(result, call->id()); 5534 ast_context()->ReturnInstruction(result, call->id());
5431 } 5535 }
5432 5536
5433 5537
5434 // Support for direct calls from JavaScript to native RegExp code. 5538 // Support for direct calls from JavaScript to native RegExp code.
5435 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { 5539 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
5436 ASSERT_EQ(4, call->arguments()->length()); 5540 ASSERT_EQ(4, call->arguments()->length());
5437 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5541 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5438 HContext* context = new(zone()) HContext; 5542 HValue* context = environment()->LookupContext();
5439 AddInstruction(context);
5440 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); 5543 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
5441 Drop(4); 5544 Drop(4);
5442 ast_context()->ReturnInstruction(result, call->id()); 5545 ast_context()->ReturnInstruction(result, call->id());
5443 } 5546 }
5444 5547
5445 5548
5446 // Construct a RegExp exec result with two in-object properties. 5549 // Construct a RegExp exec result with two in-object properties.
5447 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { 5550 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
5448 ASSERT_EQ(3, call->arguments()->length()); 5551 ASSERT_EQ(3, call->arguments()->length());
5449 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5552 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5450 HContext* context = new(zone()) HContext; 5553 HValue* context = environment()->LookupContext();
5451 AddInstruction(context);
5452 HCallStub* result = 5554 HCallStub* result =
5453 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); 5555 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
5454 Drop(3); 5556 Drop(3);
5455 ast_context()->ReturnInstruction(result, call->id()); 5557 ast_context()->ReturnInstruction(result, call->id());
5456 } 5558 }
5457 5559
5458 5560
5459 // Support for fast native caches. 5561 // Support for fast native caches.
5460 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { 5562 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
5461 return Bailout("inlined runtime function: GetFromCache"); 5563 return Bailout("inlined runtime function: GetFromCache");
5462 } 5564 }
5463 5565
5464 5566
5465 // Fast support for number to string. 5567 // Fast support for number to string.
5466 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { 5568 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
5467 ASSERT_EQ(1, call->arguments()->length()); 5569 ASSERT_EQ(1, call->arguments()->length());
5468 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5570 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5469 HContext* context = new(zone()) HContext; 5571 HValue* context = environment()->LookupContext();
5470 AddInstruction(context);
5471 HCallStub* result = 5572 HCallStub* result =
5472 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); 5573 new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
5473 Drop(1); 5574 Drop(1);
5474 ast_context()->ReturnInstruction(result, call->id()); 5575 ast_context()->ReturnInstruction(result, call->id());
5475 } 5576 }
5476 5577
5477 5578
5478 // Fast swapping of elements. Takes three expressions, the object and two 5579 // Fast swapping of elements. Takes three expressions, the object and two
5479 // indices. This should only be used if the indices are known to be 5580 // indices. This should only be used if the indices are known to be
5480 // non-negative and within bounds of the elements array at the call site. 5581 // non-negative and within bounds of the elements array at the call site.
5481 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { 5582 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) {
5482 return Bailout("inlined runtime function: SwapElements"); 5583 return Bailout("inlined runtime function: SwapElements");
5483 } 5584 }
5484 5585
5485 5586
5486 // Fast call for custom callbacks. 5587 // Fast call for custom callbacks.
5487 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { 5588 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
5488 // 1 ~ The function to call is not itself an argument to the call. 5589 // 1 ~ The function to call is not itself an argument to the call.
5489 int arg_count = call->arguments()->length() - 1; 5590 int arg_count = call->arguments()->length() - 1;
5490 ASSERT(arg_count >= 1); // There's always at least a receiver. 5591 ASSERT(arg_count >= 1); // There's always at least a receiver.
5491 5592
5492 for (int i = 0; i < arg_count; ++i) { 5593 for (int i = 0; i < arg_count; ++i) {
5493 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); 5594 CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
5494 } 5595 }
5495 CHECK_ALIVE(VisitForValue(call->arguments()->last())); 5596 CHECK_ALIVE(VisitForValue(call->arguments()->last()));
5496 HValue* function = Pop(); 5597 HValue* function = Pop();
5497 HContext* context = new HContext; 5598 HValue* context = environment()->LookupContext();
5498 AddInstruction(context);
5499 HInvokeFunction* result = 5599 HInvokeFunction* result =
5500 new(zone()) HInvokeFunction(context, function, arg_count); 5600 new(zone()) HInvokeFunction(context, function, arg_count);
5501 Drop(arg_count); 5601 Drop(arg_count);
5502 ast_context()->ReturnInstruction(result, call->id()); 5602 ast_context()->ReturnInstruction(result, call->id());
5503 } 5603 }
5504 5604
5505 5605
5506 // Fast call to math functions. 5606 // Fast call to math functions.
5507 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { 5607 void HGraphBuilder::GenerateMathPow(CallRuntime* call) {
5508 ASSERT_EQ(2, call->arguments()->length()); 5608 ASSERT_EQ(2, call->arguments()->length());
5509 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5609 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5510 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 5610 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5511 HValue* right = Pop(); 5611 HValue* right = Pop();
5512 HValue* left = Pop(); 5612 HValue* left = Pop();
5513 HPower* result = new(zone()) HPower(left, right); 5613 HPower* result = new(zone()) HPower(left, right);
5514 ast_context()->ReturnInstruction(result, call->id()); 5614 ast_context()->ReturnInstruction(result, call->id());
5515 } 5615 }
5516 5616
5517 5617
5518 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { 5618 void HGraphBuilder::GenerateMathSin(CallRuntime* call) {
5519 ASSERT_EQ(1, call->arguments()->length()); 5619 ASSERT_EQ(1, call->arguments()->length());
5520 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5620 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5521 HContext* context = new(zone()) HContext; 5621 HValue* context = environment()->LookupContext();
5522 AddInstruction(context);
5523 HCallStub* result = 5622 HCallStub* result =
5524 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 5623 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5525 result->set_transcendental_type(TranscendentalCache::SIN); 5624 result->set_transcendental_type(TranscendentalCache::SIN);
5526 Drop(1); 5625 Drop(1);
5527 ast_context()->ReturnInstruction(result, call->id()); 5626 ast_context()->ReturnInstruction(result, call->id());
5528 } 5627 }
5529 5628
5530 5629
5531 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { 5630 void HGraphBuilder::GenerateMathCos(CallRuntime* call) {
5532 ASSERT_EQ(1, call->arguments()->length()); 5631 ASSERT_EQ(1, call->arguments()->length());
5533 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5632 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5534 HContext* context = new(zone()) HContext; 5633 HValue* context = environment()->LookupContext();
5535 AddInstruction(context);
5536 HCallStub* result = 5634 HCallStub* result =
5537 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 5635 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5538 result->set_transcendental_type(TranscendentalCache::COS); 5636 result->set_transcendental_type(TranscendentalCache::COS);
5539 Drop(1); 5637 Drop(1);
5540 ast_context()->ReturnInstruction(result, call->id()); 5638 ast_context()->ReturnInstruction(result, call->id());
5541 } 5639 }
5542 5640
5543 5641
5544 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { 5642 void HGraphBuilder::GenerateMathLog(CallRuntime* call) {
5545 ASSERT_EQ(1, call->arguments()->length()); 5643 ASSERT_EQ(1, call->arguments()->length());
5546 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5644 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5547 HContext* context = new(zone()) HContext; 5645 HValue* context = environment()->LookupContext();
5548 AddInstruction(context);
5549 HCallStub* result = 5646 HCallStub* result =
5550 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 5647 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5551 result->set_transcendental_type(TranscendentalCache::LOG); 5648 result->set_transcendental_type(TranscendentalCache::LOG);
5552 Drop(1); 5649 Drop(1);
5553 ast_context()->ReturnInstruction(result, call->id()); 5650 ast_context()->ReturnInstruction(result, call->id());
5554 } 5651 }
5555 5652
5556 5653
5557 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { 5654 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
5558 return Bailout("inlined runtime function: MathSqrt"); 5655 return Bailout("inlined runtime function: MathSqrt");
(...skipping 24 matching lines...) Expand all
5583 #undef CHECK_ALIVE 5680 #undef CHECK_ALIVE
5584 5681
5585 5682
5586 HEnvironment::HEnvironment(HEnvironment* outer, 5683 HEnvironment::HEnvironment(HEnvironment* outer,
5587 Scope* scope, 5684 Scope* scope,
5588 Handle<JSFunction> closure) 5685 Handle<JSFunction> closure)
5589 : closure_(closure), 5686 : closure_(closure),
5590 values_(0), 5687 values_(0),
5591 assigned_variables_(4), 5688 assigned_variables_(4),
5592 parameter_count_(0), 5689 parameter_count_(0),
5690 specials_count_(1),
5593 local_count_(0), 5691 local_count_(0),
5594 outer_(outer), 5692 outer_(outer),
5595 pop_count_(0), 5693 pop_count_(0),
5596 push_count_(0), 5694 push_count_(0),
5597 ast_id_(AstNode::kNoNumber) { 5695 ast_id_(AstNode::kNoNumber) {
5598 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); 5696 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
5599 } 5697 }
5600 5698
5601 5699
5602 HEnvironment::HEnvironment(const HEnvironment* other) 5700 HEnvironment::HEnvironment(const HEnvironment* other)
5603 : values_(0), 5701 : values_(0),
5604 assigned_variables_(0), 5702 assigned_variables_(0),
5605 parameter_count_(0), 5703 parameter_count_(0),
5704 specials_count_(1),
5606 local_count_(0), 5705 local_count_(0),
5607 outer_(NULL), 5706 outer_(NULL),
5608 pop_count_(0), 5707 pop_count_(0),
5609 push_count_(0), 5708 push_count_(0),
5610 ast_id_(other->ast_id()) { 5709 ast_id_(other->ast_id()) {
5611 Initialize(other); 5710 Initialize(other);
5612 } 5711 }
5613 5712
5614 5713
5615 void HEnvironment::Initialize(int parameter_count, 5714 void HEnvironment::Initialize(int parameter_count,
5616 int local_count, 5715 int local_count,
5617 int stack_height) { 5716 int stack_height) {
5618 parameter_count_ = parameter_count; 5717 parameter_count_ = parameter_count;
5619 local_count_ = local_count; 5718 local_count_ = local_count;
5620 5719
5621 // Avoid reallocating the temporaries' backing store on the first Push. 5720 // Avoid reallocating the temporaries' backing store on the first Push.
5622 int total = parameter_count + local_count + stack_height; 5721 int total = parameter_count + specials_count_ + local_count + stack_height;
5623 values_.Initialize(total + 4); 5722 values_.Initialize(total + 4);
5624 for (int i = 0; i < total; ++i) values_.Add(NULL); 5723 for (int i = 0; i < total; ++i) values_.Add(NULL);
5625 } 5724 }
5626 5725
5627 5726
5628 void HEnvironment::Initialize(const HEnvironment* other) { 5727 void HEnvironment::Initialize(const HEnvironment* other) {
5629 closure_ = other->closure(); 5728 closure_ = other->closure();
5630 values_.AddAll(other->values_); 5729 values_.AddAll(other->values_);
5631 assigned_variables_.AddAll(other->assigned_variables_); 5730 assigned_variables_.AddAll(other->assigned_variables_);
5632 parameter_count_ = other->parameter_count_; 5731 parameter_count_ = other->parameter_count_;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
5671 void HEnvironment::Bind(int index, HValue* value) { 5770 void HEnvironment::Bind(int index, HValue* value) {
5672 ASSERT(value != NULL); 5771 ASSERT(value != NULL);
5673 if (!assigned_variables_.Contains(index)) { 5772 if (!assigned_variables_.Contains(index)) {
5674 assigned_variables_.Add(index); 5773 assigned_variables_.Add(index);
5675 } 5774 }
5676 values_[index] = value; 5775 values_[index] = value;
5677 } 5776 }
5678 5777
5679 5778
5680 bool HEnvironment::HasExpressionAt(int index) const { 5779 bool HEnvironment::HasExpressionAt(int index) const {
5681 return index >= parameter_count_ + local_count_; 5780 return index >= parameter_count_ + specials_count_ + local_count_;
5682 } 5781 }
5683 5782
5684 5783
5685 bool HEnvironment::ExpressionStackIsEmpty() const { 5784 bool HEnvironment::ExpressionStackIsEmpty() const {
5686 int first_expression = parameter_count() + local_count(); 5785 int first_expression = parameter_count() + specials_count() + local_count();
5687 ASSERT(length() >= first_expression); 5786 ASSERT(length() >= first_expression);
5688 return length() == first_expression; 5787 return length() == first_expression;
5689 } 5788 }
5690 5789
5691 5790
5692 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) { 5791 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
5693 int count = index_from_top + 1; 5792 int count = index_from_top + 1;
5694 int index = values_.length() - count; 5793 int index = values_.length() - count;
5695 ASSERT(HasExpressionAt(index)); 5794 ASSERT(HasExpressionAt(index));
5696 // The push count must include at least the element in question or else 5795 // The push count must include at least the element in question or else
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
5754 HValue* push = ExpressionStackAt(arity - i); 5853 HValue* push = ExpressionStackAt(arity - i);
5755 inner->SetValueAt(i, push); 5854 inner->SetValueAt(i, push);
5756 } 5855 }
5757 } else { 5856 } else {
5758 ASSERT(compilation_phase == LITHIUM); 5857 ASSERT(compilation_phase == LITHIUM);
5759 for (int i = 0; i <= arity; ++i) { // Include receiver. 5858 for (int i = 0; i <= arity; ++i) { // Include receiver.
5760 HValue* push = ExpressionStackAt(arity - i); 5859 HValue* push = ExpressionStackAt(arity - i);
5761 inner->SetValueAt(i, push); 5860 inner->SetValueAt(i, push);
5762 } 5861 }
5763 } 5862 }
5764 5863 inner->SetValueAt(arity + 1, outer->LookupContext());
5765 // Initialize the stack-allocated locals to undefined. 5864 for (int i = arity + 2; i < inner->length(); ++i) {
5766 int local_base = arity + 1; 5865 inner->SetValueAt(i, undefined);
5767 int local_count = function->scope()->num_stack_slots();
5768 for (int i = 0; i < local_count; ++i) {
5769 inner->SetValueAt(local_base + i, undefined);
5770 } 5866 }
5771 5867
5772 inner->set_ast_id(AstNode::kFunctionEntryId); 5868 inner->set_ast_id(AstNode::kFunctionEntryId);
5773 return inner; 5869 return inner;
5774 } 5870 }
5775 5871
5776 5872
5777 void HEnvironment::PrintTo(StringStream* stream) { 5873 void HEnvironment::PrintTo(StringStream* stream) {
5778 for (int i = 0; i < length(); i++) { 5874 for (int i = 0; i < length(); i++) {
5779 if (i == 0) stream->Add("parameters\n"); 5875 if (i == 0) stream->Add("parameters\n");
5780 if (i == parameter_count()) stream->Add("locals\n"); 5876 if (i == parameter_count()) stream->Add("specials\n");
5781 if (i == parameter_count() + local_count()) stream->Add("expressions"); 5877 if (i == parameter_count() + specials_count()) stream->Add("locals\n");
5878 if (i == parameter_count() + specials_count() + local_count()) {
5879 stream->Add("expressions");
5880 }
5782 HValue* val = values_.at(i); 5881 HValue* val = values_.at(i);
5783 stream->Add("%d: ", i); 5882 stream->Add("%d: ", i);
5784 if (val != NULL) { 5883 if (val != NULL) {
5785 val->PrintNameTo(stream); 5884 val->PrintNameTo(stream);
5786 } else { 5885 } else {
5787 stream->Add("NULL"); 5886 stream->Add("NULL");
5788 } 5887 }
5789 stream->Add("\n"); 5888 stream->Add("\n");
5790 } 5889 }
5791 } 5890 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
5866 LifetimePosition::FromInstructionIndex(first_index).Value()); 5965 LifetimePosition::FromInstructionIndex(first_index).Value());
5867 PrintIntProperty( 5966 PrintIntProperty(
5868 "last_lir_id", 5967 "last_lir_id",
5869 LifetimePosition::FromInstructionIndex(last_index).Value()); 5968 LifetimePosition::FromInstructionIndex(last_index).Value());
5870 } 5969 }
5871 5970
5872 { 5971 {
5873 Tag states_tag(this, "states"); 5972 Tag states_tag(this, "states");
5874 Tag locals_tag(this, "locals"); 5973 Tag locals_tag(this, "locals");
5875 int total = current->phis()->length(); 5974 int total = current->phis()->length();
5876 trace_.Add("size %d\n", total); 5975 PrintIntProperty("size", current->phis()->length());
5877 trace_.Add("method \"None\""); 5976 PrintStringProperty("method", "None");
5878 for (int j = 0; j < total; ++j) { 5977 for (int j = 0; j < total; ++j) {
5879 HPhi* phi = current->phis()->at(j); 5978 HPhi* phi = current->phis()->at(j);
5979 PrintIndent();
5880 trace_.Add("%d ", phi->merged_index()); 5980 trace_.Add("%d ", phi->merged_index());
5881 phi->PrintNameTo(&trace_); 5981 phi->PrintNameTo(&trace_);
5882 trace_.Add(" "); 5982 trace_.Add(" ");
5883 phi->PrintTo(&trace_); 5983 phi->PrintTo(&trace_);
5884 trace_.Add("\n"); 5984 trace_.Add("\n");
5885 } 5985 }
5886 } 5986 }
5887 5987
5888 { 5988 {
5889 Tag HIR_tag(this, "HIR"); 5989 Tag HIR_tag(this, "HIR");
5890 HInstruction* instruction = current->first(); 5990 HInstruction* instruction = current->first();
5891 while (instruction != NULL) { 5991 while (instruction != NULL) {
5892 int bci = 0; 5992 int bci = 0;
5893 int uses = instruction->UseCount(); 5993 int uses = instruction->UseCount();
5994 PrintIndent();
5894 trace_.Add("%d %d ", bci, uses); 5995 trace_.Add("%d %d ", bci, uses);
5895 instruction->PrintNameTo(&trace_); 5996 instruction->PrintNameTo(&trace_);
5896 trace_.Add(" "); 5997 trace_.Add(" ");
5897 instruction->PrintTo(&trace_); 5998 instruction->PrintTo(&trace_);
5898 trace_.Add(" <|@\n"); 5999 trace_.Add(" <|@\n");
5899 instruction = instruction->next(); 6000 instruction = instruction->next();
5900 } 6001 }
5901 } 6002 }
5902 6003
5903 6004
5904 if (chunk != NULL) { 6005 if (chunk != NULL) {
5905 Tag LIR_tag(this, "LIR"); 6006 Tag LIR_tag(this, "LIR");
5906 int first_index = current->first_instruction_index(); 6007 int first_index = current->first_instruction_index();
5907 int last_index = current->last_instruction_index(); 6008 int last_index = current->last_instruction_index();
5908 if (first_index != -1 && last_index != -1) { 6009 if (first_index != -1 && last_index != -1) {
5909 const ZoneList<LInstruction*>* instructions = chunk->instructions(); 6010 const ZoneList<LInstruction*>* instructions = chunk->instructions();
5910 for (int i = first_index; i <= last_index; ++i) { 6011 for (int i = first_index; i <= last_index; ++i) {
5911 LInstruction* linstr = instructions->at(i); 6012 LInstruction* linstr = instructions->at(i);
5912 if (linstr != NULL) { 6013 if (linstr != NULL) {
6014 PrintIndent();
5913 trace_.Add("%d ", 6015 trace_.Add("%d ",
5914 LifetimePosition::FromInstructionIndex(i).Value()); 6016 LifetimePosition::FromInstructionIndex(i).Value());
5915 linstr->PrintTo(&trace_); 6017 linstr->PrintTo(&trace_);
5916 trace_.Add(" <|@\n"); 6018 trace_.Add(" <|@\n");
5917 } 6019 }
5918 } 6020 }
5919 } 6021 }
5920 } 6022 }
5921 } 6023 }
5922 } 6024 }
(...skipping 15 matching lines...) Expand all
5938 6040
5939 const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges(); 6041 const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
5940 for (int i = 0; i < live_ranges->length(); ++i) { 6042 for (int i = 0; i < live_ranges->length(); ++i) {
5941 TraceLiveRange(live_ranges->at(i), "object"); 6043 TraceLiveRange(live_ranges->at(i), "object");
5942 } 6044 }
5943 } 6045 }
5944 6046
5945 6047
5946 void HTracer::TraceLiveRange(LiveRange* range, const char* type) { 6048 void HTracer::TraceLiveRange(LiveRange* range, const char* type) {
5947 if (range != NULL && !range->IsEmpty()) { 6049 if (range != NULL && !range->IsEmpty()) {
6050 PrintIndent();
5948 trace_.Add("%d %s", range->id(), type); 6051 trace_.Add("%d %s", range->id(), type);
5949 if (range->HasRegisterAssigned()) { 6052 if (range->HasRegisterAssigned()) {
5950 LOperand* op = range->CreateAssignedOperand(); 6053 LOperand* op = range->CreateAssignedOperand();
5951 int assigned_reg = op->index(); 6054 int assigned_reg = op->index();
5952 if (op->IsDoubleRegister()) { 6055 if (op->IsDoubleRegister()) {
5953 trace_.Add(" \"%s\"", 6056 trace_.Add(" \"%s\"",
5954 DoubleRegister::AllocationIndexToString(assigned_reg)); 6057 DoubleRegister::AllocationIndexToString(assigned_reg));
5955 } else { 6058 } else {
5956 ASSERT(op->IsRegister()); 6059 ASSERT(op->IsRegister());
5957 trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg)); 6060 trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
6097 } 6200 }
6098 } 6201 }
6099 6202
6100 #ifdef DEBUG 6203 #ifdef DEBUG
6101 if (graph_ != NULL) graph_->Verify(); 6204 if (graph_ != NULL) graph_->Verify();
6102 if (allocator_ != NULL) allocator_->Verify(); 6205 if (allocator_ != NULL) allocator_->Verify();
6103 #endif 6206 #endif
6104 } 6207 }
6105 6208
6106 } } // namespace v8::internal 6209 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698