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

Side by Side Diff: src/arm/codegen-arm.cc

Issue 113458: First round of size reduction for JumpTargets. Reduce their size by... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 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 | « no previous file | src/arm/jump-target-arm.cc » ('j') | src/jump-target.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 129 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
130 frame_->SpillAll(); 130 frame_->SpillAll();
131 __ stop("stop-at"); 131 __ stop("stop-at");
132 } 132 }
133 #endif 133 #endif
134 134
135 // Allocate space for locals and initialize them. 135 // Allocate space for locals and initialize them.
136 frame_->AllocateStackSlots(scope_->num_stack_slots()); 136 frame_->AllocateStackSlots(scope_->num_stack_slots());
137 // Initialize the function return target after the locals are set 137 // Initialize the function return target after the locals are set
138 // up, because it needs the expected frame height from the frame. 138 // up, because it needs the expected frame height from the frame.
139 function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL); 139 function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
140 function_return_is_shadowed_ = false; 140 function_return_is_shadowed_ = false;
141 141
142 VirtualFrame::SpilledScope spilled_scope(this); 142 VirtualFrame::SpilledScope spilled_scope(this);
143 if (scope_->num_heap_slots() > 0) { 143 if (scope_->num_heap_slots() > 0) {
144 // Allocate local context. 144 // Allocate local context.
145 // Get outer context and create a new context based on it. 145 // Get outer context and create a new context based on it.
146 __ ldr(r0, frame_->Function()); 146 __ ldr(r0, frame_->Function());
147 frame_->EmitPush(r0); 147 frame_->EmitPush(r0);
148 frame_->CallRuntime(Runtime::kNewContext, 1); // r0 holds the result 148 frame_->CallRuntime(Runtime::kNewContext, 1); // r0 holds the result
149 149
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 frame_->SpillAll(); 449 frame_->SpillAll();
450 set_in_spilled_code(true); 450 set_in_spilled_code(true);
451 } 451 }
452 452
453 453
454 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 454 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
455 #ifdef DEBUG 455 #ifdef DEBUG
456 int original_height = frame_->height(); 456 int original_height = frame_->height();
457 #endif 457 #endif
458 ASSERT(!in_spilled_code()); 458 ASSERT(!in_spilled_code());
459 JumpTarget true_target(this); 459 JumpTarget true_target;
460 JumpTarget false_target(this); 460 JumpTarget false_target;
461 LoadCondition(x, typeof_state, &true_target, &false_target, false); 461 LoadCondition(x, typeof_state, &true_target, &false_target, false);
462 462
463 if (has_cc()) { 463 if (has_cc()) {
464 // Convert cc_reg_ into a boolean value. 464 // Convert cc_reg_ into a boolean value.
465 JumpTarget loaded(this); 465 JumpTarget loaded;
466 JumpTarget materialize_true(this); 466 JumpTarget materialize_true;
467 materialize_true.Branch(cc_reg_); 467 materialize_true.Branch(cc_reg_);
468 __ mov(r0, Operand(Factory::false_value())); 468 __ mov(r0, Operand(Factory::false_value()));
469 frame_->EmitPush(r0); 469 frame_->EmitPush(r0);
470 loaded.Jump(); 470 loaded.Jump();
471 materialize_true.Bind(); 471 materialize_true.Bind();
472 __ mov(r0, Operand(Factory::true_value())); 472 __ mov(r0, Operand(Factory::true_value()));
473 frame_->EmitPush(r0); 473 frame_->EmitPush(r0);
474 loaded.Bind(); 474 loaded.Bind();
475 cc_reg_ = al; 475 cc_reg_ = al;
476 } 476 }
477 477
478 if (true_target.is_linked() || false_target.is_linked()) { 478 if (true_target.is_linked() || false_target.is_linked()) {
479 // We have at least one condition value that has been "translated" 479 // We have at least one condition value that has been "translated"
480 // into a branch, thus it needs to be loaded explicitly. 480 // into a branch, thus it needs to be loaded explicitly.
481 JumpTarget loaded(this); 481 JumpTarget loaded;
482 if (frame_ != NULL) { 482 if (frame_ != NULL) {
483 loaded.Jump(); // Don't lose the current TOS. 483 loaded.Jump(); // Don't lose the current TOS.
484 } 484 }
485 bool both = true_target.is_linked() && false_target.is_linked(); 485 bool both = true_target.is_linked() && false_target.is_linked();
486 // Load "true" if necessary. 486 // Load "true" if necessary.
487 if (true_target.is_linked()) { 487 if (true_target.is_linked()) {
488 true_target.Bind(); 488 true_target.Bind();
489 __ mov(r0, Operand(Factory::true_value())); 489 __ mov(r0, Operand(Factory::true_value()));
490 frame_->EmitPush(r0); 490 frame_->EmitPush(r0);
491 } 491 }
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 // some possible smi operations (like + and -) when (at least) one 858 // some possible smi operations (like + and -) when (at least) one
859 // of the operands is a literal smi. With this optimization, the 859 // of the operands is a literal smi. With this optimization, the
860 // performance of the system is increased by ~15%, and the generated 860 // performance of the system is increased by ~15%, and the generated
861 // code size is increased by ~1% (measured on a combination of 861 // code size is increased by ~1% (measured on a combination of
862 // different benchmarks). 862 // different benchmarks).
863 863
864 // sp[0] : operand 864 // sp[0] : operand
865 865
866 int int_value = Smi::cast(*value)->value(); 866 int int_value = Smi::cast(*value)->value();
867 867
868 JumpTarget exit(this); 868 JumpTarget exit;
869 frame_->EmitPop(r0); 869 frame_->EmitPop(r0);
870 870
871 switch (op) { 871 switch (op) {
872 case Token::ADD: { 872 case Token::ADD: {
873 DeferredCode* deferred = 873 DeferredCode* deferred =
874 new DeferredInlineSmiOperation(this, op, int_value, reversed, mode); 874 new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
875 875
876 __ add(r0, r0, Operand(value), SetCC); 876 __ add(r0, r0, Operand(value), SetCC);
877 deferred->enter()->Branch(vs); 877 deferred->enter()->Branch(vs);
878 __ tst(r0, Operand(kSmiTagMask)); 878 __ tst(r0, Operand(kSmiTagMask));
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
988 988
989 void CodeGenerator::Comparison(Condition cc, bool strict) { 989 void CodeGenerator::Comparison(Condition cc, bool strict) {
990 VirtualFrame::SpilledScope spilled_scope(this); 990 VirtualFrame::SpilledScope spilled_scope(this);
991 // sp[0] : y 991 // sp[0] : y
992 // sp[1] : x 992 // sp[1] : x
993 // result : cc register 993 // result : cc register
994 994
995 // Strict only makes sense for equality comparisons. 995 // Strict only makes sense for equality comparisons.
996 ASSERT(!strict || cc == eq); 996 ASSERT(!strict || cc == eq);
997 997
998 JumpTarget exit(this); 998 JumpTarget exit;
999 JumpTarget smi(this); 999 JumpTarget smi;
1000 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 1000 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
1001 if (cc == gt || cc == le) { 1001 if (cc == gt || cc == le) {
1002 cc = ReverseCondition(cc); 1002 cc = ReverseCondition(cc);
1003 frame_->EmitPop(r1); 1003 frame_->EmitPop(r1);
1004 frame_->EmitPop(r0); 1004 frame_->EmitPop(r0);
1005 } else { 1005 } else {
1006 frame_->EmitPop(r0); 1006 frame_->EmitPop(r0);
1007 frame_->EmitPop(r1); 1007 frame_->EmitPop(r1);
1008 } 1008 }
1009 __ orr(r2, r0, Operand(r1)); 1009 __ orr(r2, r0, Operand(r1));
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 } 1149 }
1150 1150
1151 1151
1152 void CodeGenerator::VisitBlock(Block* node) { 1152 void CodeGenerator::VisitBlock(Block* node) {
1153 #ifdef DEBUG 1153 #ifdef DEBUG
1154 int original_height = frame_->height(); 1154 int original_height = frame_->height();
1155 #endif 1155 #endif
1156 VirtualFrame::SpilledScope spilled_scope(this); 1156 VirtualFrame::SpilledScope spilled_scope(this);
1157 Comment cmnt(masm_, "[ Block"); 1157 Comment cmnt(masm_, "[ Block");
1158 CodeForStatementPosition(node); 1158 CodeForStatementPosition(node);
1159 node->break_target()->Initialize(this); 1159 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1160 VisitStatementsAndSpill(node->statements()); 1160 VisitStatementsAndSpill(node->statements());
1161 if (node->break_target()->is_linked()) { 1161 if (node->break_target()->is_linked()) {
1162 node->break_target()->Bind(); 1162 node->break_target()->Bind();
1163 } 1163 }
1164 node->break_target()->Unuse(); 1164 node->break_target()->Unuse();
1165 ASSERT(!has_valid_frame() || frame_->height() == original_height); 1165 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1166 } 1166 }
1167 1167
1168 1168
1169 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1169 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1283 #endif 1283 #endif
1284 VirtualFrame::SpilledScope spilled_scope(this); 1284 VirtualFrame::SpilledScope spilled_scope(this);
1285 Comment cmnt(masm_, "[ IfStatement"); 1285 Comment cmnt(masm_, "[ IfStatement");
1286 // Generate different code depending on which parts of the if statement 1286 // Generate different code depending on which parts of the if statement
1287 // are present or not. 1287 // are present or not.
1288 bool has_then_stm = node->HasThenStatement(); 1288 bool has_then_stm = node->HasThenStatement();
1289 bool has_else_stm = node->HasElseStatement(); 1289 bool has_else_stm = node->HasElseStatement();
1290 1290
1291 CodeForStatementPosition(node); 1291 CodeForStatementPosition(node);
1292 1292
1293 JumpTarget exit(this); 1293 JumpTarget exit;
1294 if (has_then_stm && has_else_stm) { 1294 if (has_then_stm && has_else_stm) {
1295 Comment cmnt(masm_, "[ IfThenElse"); 1295 Comment cmnt(masm_, "[ IfThenElse");
1296 JumpTarget then(this); 1296 JumpTarget then;
1297 JumpTarget else_(this); 1297 JumpTarget else_;
1298 // if (cond) 1298 // if (cond)
1299 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, 1299 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
1300 &then, &else_, true); 1300 &then, &else_, true);
1301 if (frame_ != NULL) { 1301 if (frame_ != NULL) {
1302 Branch(false, &else_); 1302 Branch(false, &else_);
1303 } 1303 }
1304 // then 1304 // then
1305 if (frame_ != NULL || then.is_linked()) { 1305 if (frame_ != NULL || then.is_linked()) {
1306 then.Bind(); 1306 then.Bind();
1307 VisitAndSpill(node->then_statement()); 1307 VisitAndSpill(node->then_statement());
1308 } 1308 }
1309 if (frame_ != NULL) { 1309 if (frame_ != NULL) {
1310 exit.Jump(); 1310 exit.Jump();
1311 } 1311 }
1312 // else 1312 // else
1313 if (else_.is_linked()) { 1313 if (else_.is_linked()) {
1314 else_.Bind(); 1314 else_.Bind();
1315 VisitAndSpill(node->else_statement()); 1315 VisitAndSpill(node->else_statement());
1316 } 1316 }
1317 1317
1318 } else if (has_then_stm) { 1318 } else if (has_then_stm) {
1319 Comment cmnt(masm_, "[ IfThen"); 1319 Comment cmnt(masm_, "[ IfThen");
1320 ASSERT(!has_else_stm); 1320 ASSERT(!has_else_stm);
1321 JumpTarget then(this); 1321 JumpTarget then;
1322 // if (cond) 1322 // if (cond)
1323 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, 1323 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
1324 &then, &exit, true); 1324 &then, &exit, true);
1325 if (frame_ != NULL) { 1325 if (frame_ != NULL) {
1326 Branch(false, &exit); 1326 Branch(false, &exit);
1327 } 1327 }
1328 // then 1328 // then
1329 if (frame_ != NULL || then.is_linked()) { 1329 if (frame_ != NULL || then.is_linked()) {
1330 then.Bind(); 1330 then.Bind();
1331 VisitAndSpill(node->then_statement()); 1331 VisitAndSpill(node->then_statement());
1332 } 1332 }
1333 1333
1334 } else if (has_else_stm) { 1334 } else if (has_else_stm) {
1335 Comment cmnt(masm_, "[ IfElse"); 1335 Comment cmnt(masm_, "[ IfElse");
1336 ASSERT(!has_then_stm); 1336 ASSERT(!has_then_stm);
1337 JumpTarget else_(this); 1337 JumpTarget else_;
1338 // if (!cond) 1338 // if (!cond)
1339 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, 1339 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
1340 &exit, &else_, true); 1340 &exit, &else_, true);
1341 if (frame_ != NULL) { 1341 if (frame_ != NULL) {
1342 Branch(true, &exit); 1342 Branch(true, &exit);
1343 } 1343 }
1344 // else 1344 // else
1345 if (frame_ != NULL || else_.is_linked()) { 1345 if (frame_ != NULL || else_.is_linked()) {
1346 else_.Bind(); 1346 else_.Bind();
1347 VisitAndSpill(node->else_statement()); 1347 VisitAndSpill(node->else_statement());
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 VirtualFrame::SpilledScope spilled_scope(this); 1417 VirtualFrame::SpilledScope spilled_scope(this);
1418 Comment cmnt(masm_, "[ WithEnterStatement"); 1418 Comment cmnt(masm_, "[ WithEnterStatement");
1419 CodeForStatementPosition(node); 1419 CodeForStatementPosition(node);
1420 LoadAndSpill(node->expression()); 1420 LoadAndSpill(node->expression());
1421 if (node->is_catch_block()) { 1421 if (node->is_catch_block()) {
1422 frame_->CallRuntime(Runtime::kPushCatchContext, 1); 1422 frame_->CallRuntime(Runtime::kPushCatchContext, 1);
1423 } else { 1423 } else {
1424 frame_->CallRuntime(Runtime::kPushContext, 1); 1424 frame_->CallRuntime(Runtime::kPushContext, 1);
1425 } 1425 }
1426 #ifdef DEBUG 1426 #ifdef DEBUG
1427 JumpTarget verified_true(this); 1427 JumpTarget verified_true;
1428 __ cmp(r0, Operand(cp)); 1428 __ cmp(r0, Operand(cp));
1429 verified_true.Branch(eq); 1429 verified_true.Branch(eq);
1430 __ stop("PushContext: r0 is expected to be the same as cp"); 1430 __ stop("PushContext: r0 is expected to be the same as cp");
1431 verified_true.Bind(); 1431 verified_true.Bind();
1432 #endif 1432 #endif
1433 // Update context local. 1433 // Update context local.
1434 __ str(cp, frame_->Context()); 1434 __ str(cp, frame_->Context());
1435 ASSERT(frame_->height() == original_height); 1435 ASSERT(frame_->height() == original_height);
1436 } 1436 }
1437 1437
(...skipping 23 matching lines...) Expand all
1461 1461
1462 1462
1463 void CodeGenerator::GenerateFastCaseSwitchJumpTable( 1463 void CodeGenerator::GenerateFastCaseSwitchJumpTable(
1464 SwitchStatement* node, 1464 SwitchStatement* node,
1465 int min_index, 1465 int min_index,
1466 int range, 1466 int range,
1467 Label* default_label, 1467 Label* default_label,
1468 Vector<Label*> case_targets, 1468 Vector<Label*> case_targets,
1469 Vector<Label> case_labels) { 1469 Vector<Label> case_labels) {
1470 VirtualFrame::SpilledScope spilled_scope(this); 1470 VirtualFrame::SpilledScope spilled_scope(this);
1471 JumpTarget setup_default(this); 1471 JumpTarget setup_default;
1472 JumpTarget is_smi(this); 1472 JumpTarget is_smi;
1473 1473
1474 // A non-null default label pointer indicates a default case among 1474 // A non-null default label pointer indicates a default case among
1475 // the case labels. Otherwise we use the break target as a 1475 // the case labels. Otherwise we use the break target as a
1476 // "default" for failure to hit the jump table. 1476 // "default" for failure to hit the jump table.
1477 JumpTarget* default_target = 1477 JumpTarget* default_target =
1478 (default_label == NULL) ? node->break_target() : &setup_default; 1478 (default_label == NULL) ? node->break_target() : &setup_default;
1479 1479
1480 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2); 1480 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
1481 frame_->EmitPop(r0); 1481 frame_->EmitPop(r0);
1482 1482
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1532 } 1532 }
1533 1533
1534 1534
1535 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 1535 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
1536 #ifdef DEBUG 1536 #ifdef DEBUG
1537 int original_height = frame_->height(); 1537 int original_height = frame_->height();
1538 #endif 1538 #endif
1539 VirtualFrame::SpilledScope spilled_scope(this); 1539 VirtualFrame::SpilledScope spilled_scope(this);
1540 Comment cmnt(masm_, "[ SwitchStatement"); 1540 Comment cmnt(masm_, "[ SwitchStatement");
1541 CodeForStatementPosition(node); 1541 CodeForStatementPosition(node);
1542 node->break_target()->Initialize(this); 1542 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1543 1543
1544 LoadAndSpill(node->tag()); 1544 LoadAndSpill(node->tag());
1545 if (TryGenerateFastCaseSwitchStatement(node)) { 1545 if (TryGenerateFastCaseSwitchStatement(node)) {
1546 ASSERT(!has_valid_frame() || frame_->height() == original_height); 1546 ASSERT(!has_valid_frame() || frame_->height() == original_height);
1547 return; 1547 return;
1548 } 1548 }
1549 1549
1550 JumpTarget next_test(this); 1550 JumpTarget next_test;
1551 JumpTarget fall_through(this); 1551 JumpTarget fall_through;
1552 JumpTarget default_entry(this); 1552 JumpTarget default_entry;
1553 JumpTarget default_exit(this, JumpTarget::BIDIRECTIONAL); 1553 JumpTarget default_exit(JumpTarget::BIDIRECTIONAL);
1554 ZoneList<CaseClause*>* cases = node->cases(); 1554 ZoneList<CaseClause*>* cases = node->cases();
1555 int length = cases->length(); 1555 int length = cases->length();
1556 CaseClause* default_clause = NULL; 1556 CaseClause* default_clause = NULL;
1557 1557
1558 for (int i = 0; i < length; i++) { 1558 for (int i = 0; i < length; i++) {
1559 CaseClause* clause = cases->at(i); 1559 CaseClause* clause = cases->at(i);
1560 if (clause->is_default()) { 1560 if (clause->is_default()) {
1561 // Remember the default clause and compile it at the end. 1561 // Remember the default clause and compile it at the end.
1562 default_clause = clause; 1562 default_clause = clause;
1563 continue; 1563 continue;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1626 } 1626 }
1627 1627
1628 1628
1629 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1629 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
1630 #ifdef DEBUG 1630 #ifdef DEBUG
1631 int original_height = frame_->height(); 1631 int original_height = frame_->height();
1632 #endif 1632 #endif
1633 VirtualFrame::SpilledScope spilled_scope(this); 1633 VirtualFrame::SpilledScope spilled_scope(this);
1634 Comment cmnt(masm_, "[ LoopStatement"); 1634 Comment cmnt(masm_, "[ LoopStatement");
1635 CodeForStatementPosition(node); 1635 CodeForStatementPosition(node);
1636 node->break_target()->Initialize(this); 1636 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1637 1637
1638 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a 1638 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
1639 // known result for the test expression, with no side effects. 1639 // known result for the test expression, with no side effects.
1640 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; 1640 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
1641 if (node->cond() == NULL) { 1641 if (node->cond() == NULL) {
1642 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1642 ASSERT(node->type() == LoopStatement::FOR_LOOP);
1643 info = ALWAYS_TRUE; 1643 info = ALWAYS_TRUE;
1644 } else { 1644 } else {
1645 Literal* lit = node->cond()->AsLiteral(); 1645 Literal* lit = node->cond()->AsLiteral();
1646 if (lit != NULL) { 1646 if (lit != NULL) {
1647 if (lit->IsTrue()) { 1647 if (lit->IsTrue()) {
1648 info = ALWAYS_TRUE; 1648 info = ALWAYS_TRUE;
1649 } else if (lit->IsFalse()) { 1649 } else if (lit->IsFalse()) {
1650 info = ALWAYS_FALSE; 1650 info = ALWAYS_FALSE;
1651 } 1651 }
1652 } 1652 }
1653 } 1653 }
1654 1654
1655 switch (node->type()) { 1655 switch (node->type()) {
1656 case LoopStatement::DO_LOOP: { 1656 case LoopStatement::DO_LOOP: {
1657 JumpTarget body(this, JumpTarget::BIDIRECTIONAL); 1657 JumpTarget body(JumpTarget::BIDIRECTIONAL);
1658 1658
1659 // Label the top of the loop for the backward CFG edge. If the test 1659 // Label the top of the loop for the backward CFG edge. If the test
1660 // is always true we can use the continue target, and if the test is 1660 // is always true we can use the continue target, and if the test is
1661 // always false there is no need. 1661 // always false there is no need.
1662 if (info == ALWAYS_TRUE) { 1662 if (info == ALWAYS_TRUE) {
1663 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 1663 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1664 node->continue_target()->Bind(); 1664 node->continue_target()->Bind();
1665 } else if (info == ALWAYS_FALSE) { 1665 } else if (info == ALWAYS_FALSE) {
1666 node->continue_target()->Initialize(this); 1666 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1667 } else { 1667 } else {
1668 ASSERT(info == DONT_KNOW); 1668 ASSERT(info == DONT_KNOW);
1669 node->continue_target()->Initialize(this); 1669 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1670 body.Bind(); 1670 body.Bind();
1671 } 1671 }
1672 1672
1673 CheckStack(); // TODO(1222600): ignore if body contains calls. 1673 CheckStack(); // TODO(1222600): ignore if body contains calls.
1674 VisitAndSpill(node->body()); 1674 VisitAndSpill(node->body());
1675 1675
1676 // Compile the test. 1676 // Compile the test.
1677 if (info == ALWAYS_TRUE) { 1677 if (info == ALWAYS_TRUE) {
1678 if (has_valid_frame()) { 1678 if (has_valid_frame()) {
1679 // If control can fall off the end of the body, jump back to the 1679 // If control can fall off the end of the body, jump back to the
(...skipping 26 matching lines...) Expand all
1706 break; 1706 break;
1707 } 1707 }
1708 1708
1709 case LoopStatement::WHILE_LOOP: { 1709 case LoopStatement::WHILE_LOOP: {
1710 // If the test is never true and has no side effects there is no need 1710 // If the test is never true and has no side effects there is no need
1711 // to compile the test or body. 1711 // to compile the test or body.
1712 if (info == ALWAYS_FALSE) break; 1712 if (info == ALWAYS_FALSE) break;
1713 1713
1714 // Label the top of the loop with the continue target for the backward 1714 // Label the top of the loop with the continue target for the backward
1715 // CFG edge. 1715 // CFG edge.
1716 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 1716 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1717 node->continue_target()->Bind(); 1717 node->continue_target()->Bind();
1718 1718
1719 if (info == DONT_KNOW) { 1719 if (info == DONT_KNOW) {
1720 JumpTarget body(this); 1720 JumpTarget body;
1721 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, 1721 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
1722 &body, node->break_target(), true); 1722 &body, node->break_target(), true);
1723 if (has_valid_frame()) { 1723 if (has_valid_frame()) {
1724 // A NULL frame indicates that control did not fall out of the 1724 // A NULL frame indicates that control did not fall out of the
1725 // test expression. 1725 // test expression.
1726 Branch(false, node->break_target()); 1726 Branch(false, node->break_target());
1727 } 1727 }
1728 if (has_valid_frame() || body.is_linked()) { 1728 if (has_valid_frame() || body.is_linked()) {
1729 body.Bind(); 1729 body.Bind();
1730 } 1730 }
1731 } 1731 }
1732 1732
1733 if (has_valid_frame()) { 1733 if (has_valid_frame()) {
1734 CheckStack(); // TODO(1222600): ignore if body contains calls. 1734 CheckStack(); // TODO(1222600): ignore if body contains calls.
1735 VisitAndSpill(node->body()); 1735 VisitAndSpill(node->body());
1736 1736
1737 // If control flow can fall out of the body, jump back to the top. 1737 // If control flow can fall out of the body, jump back to the top.
1738 if (has_valid_frame()) { 1738 if (has_valid_frame()) {
1739 node->continue_target()->Jump(); 1739 node->continue_target()->Jump();
1740 } 1740 }
1741 } 1741 }
1742 break; 1742 break;
1743 } 1743 }
1744 1744
1745 case LoopStatement::FOR_LOOP: { 1745 case LoopStatement::FOR_LOOP: {
1746 JumpTarget loop(this, JumpTarget::BIDIRECTIONAL); 1746 JumpTarget loop(JumpTarget::BIDIRECTIONAL);
1747 1747
1748 if (node->init() != NULL) { 1748 if (node->init() != NULL) {
1749 VisitAndSpill(node->init()); 1749 VisitAndSpill(node->init());
1750 } 1750 }
1751 1751
1752 // There is no need to compile the test or body. 1752 // There is no need to compile the test or body.
1753 if (info == ALWAYS_FALSE) break; 1753 if (info == ALWAYS_FALSE) break;
1754 1754
1755 // If there is no update statement, label the top of the loop with the 1755 // If there is no update statement, label the top of the loop with the
1756 // continue target, otherwise with the loop target. 1756 // continue target, otherwise with the loop target.
1757 if (node->next() == NULL) { 1757 if (node->next() == NULL) {
1758 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 1758 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1759 node->continue_target()->Bind(); 1759 node->continue_target()->Bind();
1760 } else { 1760 } else {
1761 node->continue_target()->Initialize(this); 1761 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1762 loop.Bind(); 1762 loop.Bind();
1763 } 1763 }
1764 1764
1765 // If the test is always true, there is no need to compile it. 1765 // If the test is always true, there is no need to compile it.
1766 if (info == DONT_KNOW) { 1766 if (info == DONT_KNOW) {
1767 JumpTarget body(this); 1767 JumpTarget body;
1768 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, 1768 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
1769 &body, node->break_target(), true); 1769 &body, node->break_target(), true);
1770 if (has_valid_frame()) { 1770 if (has_valid_frame()) {
1771 Branch(false, node->break_target()); 1771 Branch(false, node->break_target());
1772 } 1772 }
1773 if (has_valid_frame() || body.is_linked()) { 1773 if (has_valid_frame() || body.is_linked()) {
1774 body.Bind(); 1774 body.Bind();
1775 } 1775 }
1776 } 1776 }
1777 1777
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1817 1817
1818 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 1818 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
1819 #ifdef DEBUG 1819 #ifdef DEBUG
1820 int original_height = frame_->height(); 1820 int original_height = frame_->height();
1821 #endif 1821 #endif
1822 ASSERT(!in_spilled_code()); 1822 ASSERT(!in_spilled_code());
1823 VirtualFrame::SpilledScope spilled_scope(this); 1823 VirtualFrame::SpilledScope spilled_scope(this);
1824 Comment cmnt(masm_, "[ ForInStatement"); 1824 Comment cmnt(masm_, "[ ForInStatement");
1825 CodeForStatementPosition(node); 1825 CodeForStatementPosition(node);
1826 1826
1827 JumpTarget primitive(this); 1827 JumpTarget primitive;
1828 JumpTarget jsobject(this); 1828 JumpTarget jsobject;
1829 JumpTarget fixed_array(this); 1829 JumpTarget fixed_array;
1830 JumpTarget entry(this, JumpTarget::BIDIRECTIONAL); 1830 JumpTarget entry(JumpTarget::BIDIRECTIONAL);
1831 JumpTarget end_del_check(this); 1831 JumpTarget end_del_check;
1832 JumpTarget exit(this); 1832 JumpTarget exit;
1833 1833
1834 // Get the object to enumerate over (converted to JSObject). 1834 // Get the object to enumerate over (converted to JSObject).
1835 LoadAndSpill(node->enumerable()); 1835 LoadAndSpill(node->enumerable());
1836 1836
1837 // Both SpiderMonkey and kjs ignore null and undefined in contrast 1837 // Both SpiderMonkey and kjs ignore null and undefined in contrast
1838 // to the specification. 12.6.4 mandates a call to ToObject. 1838 // to the specification. 12.6.4 mandates a call to ToObject.
1839 frame_->EmitPop(r0); 1839 frame_->EmitPop(r0);
1840 __ cmp(r0, Operand(Factory::undefined_value())); 1840 __ cmp(r0, Operand(Factory::undefined_value()));
1841 exit.Branch(eq); 1841 exit.Branch(eq);
1842 __ cmp(r0, Operand(Factory::null_value())); 1842 __ cmp(r0, Operand(Factory::null_value()));
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 1907
1908 // Condition. 1908 // Condition.
1909 entry.Bind(); 1909 entry.Bind();
1910 // sp[0] : index 1910 // sp[0] : index
1911 // sp[1] : array/enum cache length 1911 // sp[1] : array/enum cache length
1912 // sp[2] : array or enum cache 1912 // sp[2] : array or enum cache
1913 // sp[3] : 0 or map 1913 // sp[3] : 0 or map
1914 // sp[4] : enumerable 1914 // sp[4] : enumerable
1915 // Grab the current frame's height for the break and continue 1915 // Grab the current frame's height for the break and continue
1916 // targets only after all the state is pushed on the frame. 1916 // targets only after all the state is pushed on the frame.
1917 node->break_target()->Initialize(this); 1917 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1918 node->continue_target()->Initialize(this); 1918 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1919 1919
1920 __ ldr(r0, frame_->ElementAt(0)); // load the current count 1920 __ ldr(r0, frame_->ElementAt(0)); // load the current count
1921 __ ldr(r1, frame_->ElementAt(1)); // load the length 1921 __ ldr(r1, frame_->ElementAt(1)); // load the length
1922 __ cmp(r0, Operand(r1)); // compare to the array length 1922 __ cmp(r0, Operand(r1)); // compare to the array length
1923 node->break_target()->Branch(hs); 1923 node->break_target()->Branch(hs);
1924 1924
1925 __ ldr(r0, frame_->ElementAt(0)); 1925 __ ldr(r0, frame_->ElementAt(0));
1926 1926
1927 // Get the i'th entry of the array. 1927 // Get the i'th entry of the array.
1928 __ ldr(r2, frame_->ElementAt(2)); 1928 __ ldr(r2, frame_->ElementAt(2));
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 2011
2012 2012
2013 void CodeGenerator::VisitTryCatch(TryCatch* node) { 2013 void CodeGenerator::VisitTryCatch(TryCatch* node) {
2014 #ifdef DEBUG 2014 #ifdef DEBUG
2015 int original_height = frame_->height(); 2015 int original_height = frame_->height();
2016 #endif 2016 #endif
2017 VirtualFrame::SpilledScope spilled_scope(this); 2017 VirtualFrame::SpilledScope spilled_scope(this);
2018 Comment cmnt(masm_, "[ TryCatch"); 2018 Comment cmnt(masm_, "[ TryCatch");
2019 CodeForStatementPosition(node); 2019 CodeForStatementPosition(node);
2020 2020
2021 JumpTarget try_block(this); 2021 JumpTarget try_block;
2022 JumpTarget exit(this); 2022 JumpTarget exit;
2023 2023
2024 try_block.Call(); 2024 try_block.Call();
2025 // --- Catch block --- 2025 // --- Catch block ---
2026 frame_->EmitPush(r0); 2026 frame_->EmitPush(r0);
2027 2027
2028 // Store the caught exception in the catch variable. 2028 // Store the caught exception in the catch variable.
2029 { Reference ref(this, node->catch_var()); 2029 { Reference ref(this, node->catch_var());
2030 ASSERT(ref.is_slot()); 2030 ASSERT(ref.is_slot());
2031 // Here we make use of the convenient property that it doesn't matter 2031 // Here we make use of the convenient property that it doesn't matter
2032 // whether a value is immediately on top of or underneath a zero-sized 2032 // whether a value is immediately on top of or underneath a zero-sized
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
2143 #endif 2143 #endif
2144 VirtualFrame::SpilledScope spilled_scope(this); 2144 VirtualFrame::SpilledScope spilled_scope(this);
2145 Comment cmnt(masm_, "[ TryFinally"); 2145 Comment cmnt(masm_, "[ TryFinally");
2146 CodeForStatementPosition(node); 2146 CodeForStatementPosition(node);
2147 2147
2148 // State: Used to keep track of reason for entering the finally 2148 // State: Used to keep track of reason for entering the finally
2149 // block. Should probably be extended to hold information for 2149 // block. Should probably be extended to hold information for
2150 // break/continue from within the try block. 2150 // break/continue from within the try block.
2151 enum { FALLING, THROWING, JUMPING }; 2151 enum { FALLING, THROWING, JUMPING };
2152 2152
2153 JumpTarget try_block(this); 2153 JumpTarget try_block;
2154 JumpTarget finally_block(this); 2154 JumpTarget finally_block;
2155 2155
2156 try_block.Call(); 2156 try_block.Call();
2157 2157
2158 frame_->EmitPush(r0); // save exception object on the stack 2158 frame_->EmitPush(r0); // save exception object on the stack
2159 // In case of thrown exceptions, this is where we continue. 2159 // In case of thrown exceptions, this is where we continue.
2160 __ mov(r2, Operand(Smi::FromInt(THROWING))); 2160 __ mov(r2, Operand(Smi::FromInt(THROWING)));
2161 finally_block.Jump(); 2161 finally_block.Jump();
2162 2162
2163 // --- Try block --- 2163 // --- Try block ---
2164 try_block.Bind(); 2164 try_block.Bind();
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2289 frame_->EmitPop(r0); 2289 frame_->EmitPop(r0);
2290 } 2290 }
2291 2291
2292 // Generate code to jump to the right destination for all used 2292 // Generate code to jump to the right destination for all used
2293 // formerly shadowing targets. Deallocate each shadow target. 2293 // formerly shadowing targets. Deallocate each shadow target.
2294 for (int i = 0; i < shadows.length(); i++) { 2294 for (int i = 0; i < shadows.length(); i++) {
2295 if (has_valid_frame() && shadows[i]->is_bound()) { 2295 if (has_valid_frame() && shadows[i]->is_bound()) {
2296 JumpTarget* original = shadows[i]->other_target(); 2296 JumpTarget* original = shadows[i]->other_target();
2297 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); 2297 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i)));
2298 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { 2298 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
2299 JumpTarget skip(this); 2299 JumpTarget skip;
2300 skip.Branch(ne); 2300 skip.Branch(ne);
2301 frame_->PrepareForReturn(); 2301 frame_->PrepareForReturn();
2302 original->Jump(); 2302 original->Jump();
2303 skip.Bind(); 2303 skip.Bind();
2304 } else { 2304 } else {
2305 original->Branch(eq); 2305 original->Branch(eq);
2306 } 2306 }
2307 } 2307 }
2308 } 2308 }
2309 2309
2310 if (has_valid_frame()) { 2310 if (has_valid_frame()) {
2311 // Check if we need to rethrow the exception. 2311 // Check if we need to rethrow the exception.
2312 JumpTarget exit(this); 2312 JumpTarget exit;
2313 __ cmp(r2, Operand(Smi::FromInt(THROWING))); 2313 __ cmp(r2, Operand(Smi::FromInt(THROWING)));
2314 exit.Branch(ne); 2314 exit.Branch(ne);
2315 2315
2316 // Rethrow exception. 2316 // Rethrow exception.
2317 frame_->EmitPush(r0); 2317 frame_->EmitPush(r0);
2318 frame_->CallRuntime(Runtime::kReThrow, 1); 2318 frame_->CallRuntime(Runtime::kReThrow, 1);
2319 2319
2320 // Done. 2320 // Done.
2321 exit.Bind(); 2321 exit.Bind();
2322 } 2322 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 ASSERT(frame_->height() == original_height + 1); 2384 ASSERT(frame_->height() == original_height + 1);
2385 } 2385 }
2386 2386
2387 2387
2388 void CodeGenerator::VisitConditional(Conditional* node) { 2388 void CodeGenerator::VisitConditional(Conditional* node) {
2389 #ifdef DEBUG 2389 #ifdef DEBUG
2390 int original_height = frame_->height(); 2390 int original_height = frame_->height();
2391 #endif 2391 #endif
2392 VirtualFrame::SpilledScope spilled_scope(this); 2392 VirtualFrame::SpilledScope spilled_scope(this);
2393 Comment cmnt(masm_, "[ Conditional"); 2393 Comment cmnt(masm_, "[ Conditional");
2394 JumpTarget then(this); 2394 JumpTarget then;
2395 JumpTarget else_(this); 2395 JumpTarget else_;
2396 JumpTarget exit(this); 2396 JumpTarget exit;
2397 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, 2397 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
2398 &then, &else_, true); 2398 &then, &else_, true);
2399 Branch(false, &else_); 2399 Branch(false, &else_);
2400 then.Bind(); 2400 then.Bind();
2401 LoadAndSpill(node->then_expression(), typeof_state()); 2401 LoadAndSpill(node->then_expression(), typeof_state());
2402 exit.Jump(); 2402 exit.Jump();
2403 else_.Bind(); 2403 else_.Bind();
2404 LoadAndSpill(node->else_expression(), typeof_state()); 2404 LoadAndSpill(node->else_expression(), typeof_state());
2405 exit.Bind(); 2405 exit.Bind();
2406 ASSERT(frame_->height() == original_height + 1); 2406 ASSERT(frame_->height() == original_height + 1);
2407 } 2407 }
2408 2408
2409 2409
2410 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2410 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2411 VirtualFrame::SpilledScope spilled_scope(this); 2411 VirtualFrame::SpilledScope spilled_scope(this);
2412 if (slot->type() == Slot::LOOKUP) { 2412 if (slot->type() == Slot::LOOKUP) {
2413 ASSERT(slot->var()->is_dynamic()); 2413 ASSERT(slot->var()->is_dynamic());
2414 2414
2415 JumpTarget slow(this); 2415 JumpTarget slow;
2416 JumpTarget done(this); 2416 JumpTarget done;
2417 2417
2418 // Generate fast-case code for variables that might be shadowed by 2418 // Generate fast-case code for variables that might be shadowed by
2419 // eval-introduced variables. Eval is used a lot without 2419 // eval-introduced variables. Eval is used a lot without
2420 // introducing variables. In those cases, we do not want to 2420 // introducing variables. In those cases, we do not want to
2421 // perform a runtime call for all variables in the scope 2421 // perform a runtime call for all variables in the scope
2422 // containing the eval. 2422 // containing the eval.
2423 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 2423 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
2424 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, r1, r2, &slow); 2424 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, r1, r2, &slow);
2425 // If there was no control flow to slow, we can exit early. 2425 // If there was no control flow to slow, we can exit early.
2426 if (!slow.is_linked()) { 2426 if (!slow.is_linked()) {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
2613 __ ldr(r1, frame_->Function()); 2613 __ ldr(r1, frame_->Function());
2614 2614
2615 // Load the literals array of the function. 2615 // Load the literals array of the function.
2616 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); 2616 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
2617 2617
2618 // Load the literal at the ast saved index. 2618 // Load the literal at the ast saved index.
2619 int literal_offset = 2619 int literal_offset =
2620 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2620 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
2621 __ ldr(r2, FieldMemOperand(r1, literal_offset)); 2621 __ ldr(r2, FieldMemOperand(r1, literal_offset));
2622 2622
2623 JumpTarget done(this); 2623 JumpTarget done;
2624 __ cmp(r2, Operand(Factory::undefined_value())); 2624 __ cmp(r2, Operand(Factory::undefined_value()));
2625 done.Branch(ne); 2625 done.Branch(ne);
2626 2626
2627 // If the entry is undefined we call the runtime system to computed 2627 // If the entry is undefined we call the runtime system to computed
2628 // the literal. 2628 // the literal.
2629 frame_->EmitPush(r1); // literal array (0) 2629 frame_->EmitPush(r1); // literal array (0)
2630 __ mov(r0, Operand(Smi::FromInt(node->literal_index()))); 2630 __ mov(r0, Operand(Smi::FromInt(node->literal_index())));
2631 frame_->EmitPush(r0); // literal index (1) 2631 frame_->EmitPush(r0); // literal index (1)
2632 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2) 2632 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2)
2633 frame_->EmitPush(r0); 2633 frame_->EmitPush(r0);
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after
3259 3259
3260 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). 3260 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
3261 __ str(r0, frame_->Top()); 3261 __ str(r0, frame_->Top());
3262 ASSERT(frame_->height() == original_height + 1); 3262 ASSERT(frame_->height() == original_height + 1);
3263 } 3263 }
3264 3264
3265 3265
3266 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 3266 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
3267 VirtualFrame::SpilledScope spilled_scope(this); 3267 VirtualFrame::SpilledScope spilled_scope(this);
3268 ASSERT(args->length() == 1); 3268 ASSERT(args->length() == 1);
3269 JumpTarget leave(this); 3269 JumpTarget leave;
3270 LoadAndSpill(args->at(0)); 3270 LoadAndSpill(args->at(0));
3271 frame_->EmitPop(r0); // r0 contains object. 3271 frame_->EmitPop(r0); // r0 contains object.
3272 // if (object->IsSmi()) return the object. 3272 // if (object->IsSmi()) return the object.
3273 __ tst(r0, Operand(kSmiTagMask)); 3273 __ tst(r0, Operand(kSmiTagMask));
3274 leave.Branch(eq); 3274 leave.Branch(eq);
3275 // It is a heap object - get map. 3275 // It is a heap object - get map.
3276 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 3276 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
3277 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 3277 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3278 // if (!object->IsJSValue()) return the object. 3278 // if (!object->IsJSValue()) return the object.
3279 __ cmp(r1, Operand(JS_VALUE_TYPE)); 3279 __ cmp(r1, Operand(JS_VALUE_TYPE));
3280 leave.Branch(ne); 3280 leave.Branch(ne);
3281 // Load the value. 3281 // Load the value.
3282 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 3282 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
3283 leave.Bind(); 3283 leave.Bind();
3284 frame_->EmitPush(r0); 3284 frame_->EmitPush(r0);
3285 } 3285 }
3286 3286
3287 3287
3288 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 3288 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
3289 VirtualFrame::SpilledScope spilled_scope(this); 3289 VirtualFrame::SpilledScope spilled_scope(this);
3290 ASSERT(args->length() == 2); 3290 ASSERT(args->length() == 2);
3291 JumpTarget leave(this); 3291 JumpTarget leave;
3292 LoadAndSpill(args->at(0)); // Load the object. 3292 LoadAndSpill(args->at(0)); // Load the object.
3293 LoadAndSpill(args->at(1)); // Load the value. 3293 LoadAndSpill(args->at(1)); // Load the value.
3294 frame_->EmitPop(r0); // r0 contains value 3294 frame_->EmitPop(r0); // r0 contains value
3295 frame_->EmitPop(r1); // r1 contains object 3295 frame_->EmitPop(r1); // r1 contains object
3296 // if (object->IsSmi()) return object. 3296 // if (object->IsSmi()) return object.
3297 __ tst(r1, Operand(kSmiTagMask)); 3297 __ tst(r1, Operand(kSmiTagMask));
3298 leave.Branch(eq); 3298 leave.Branch(eq);
3299 // It is a heap object - get map. 3299 // It is a heap object - get map.
3300 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3300 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
3301 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 3301 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
3357 ASSERT(args->length() == 2); 3357 ASSERT(args->length() == 2);
3358 __ mov(r0, Operand(Factory::undefined_value())); 3358 __ mov(r0, Operand(Factory::undefined_value()));
3359 frame_->EmitPush(r0); 3359 frame_->EmitPush(r0);
3360 } 3360 }
3361 3361
3362 3362
3363 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3363 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3364 VirtualFrame::SpilledScope spilled_scope(this); 3364 VirtualFrame::SpilledScope spilled_scope(this);
3365 ASSERT(args->length() == 1); 3365 ASSERT(args->length() == 1);
3366 LoadAndSpill(args->at(0)); 3366 LoadAndSpill(args->at(0));
3367 JumpTarget answer(this); 3367 JumpTarget answer;
3368 // We need the CC bits to come out as not_equal in the case where the 3368 // We need the CC bits to come out as not_equal in the case where the
3369 // object is a smi. This can't be done with the usual test opcode so 3369 // object is a smi. This can't be done with the usual test opcode so
3370 // we use XOR to get the right CC bits. 3370 // we use XOR to get the right CC bits.
3371 frame_->EmitPop(r0); 3371 frame_->EmitPop(r0);
3372 __ and_(r1, r0, Operand(kSmiTagMask)); 3372 __ and_(r1, r0, Operand(kSmiTagMask));
3373 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); 3373 __ eor(r1, r1, Operand(kSmiTagMask), SetCC);
3374 answer.Branch(ne); 3374 answer.Branch(ne);
3375 // It is a heap object - get the map. 3375 // It is a heap object - get the map.
3376 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 3376 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
3377 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 3377 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
3561 break; 3561 break;
3562 3562
3563 case Token::SUB: { 3563 case Token::SUB: {
3564 UnarySubStub stub; 3564 UnarySubStub stub;
3565 frame_->CallStub(&stub, 0); 3565 frame_->CallStub(&stub, 0);
3566 break; 3566 break;
3567 } 3567 }
3568 3568
3569 case Token::BIT_NOT: { 3569 case Token::BIT_NOT: {
3570 // smi check 3570 // smi check
3571 JumpTarget smi_label(this); 3571 JumpTarget smi_label;
3572 JumpTarget continue_label(this); 3572 JumpTarget continue_label;
3573 __ tst(r0, Operand(kSmiTagMask)); 3573 __ tst(r0, Operand(kSmiTagMask));
3574 smi_label.Branch(eq); 3574 smi_label.Branch(eq);
3575 3575
3576 frame_->EmitPush(r0); 3576 frame_->EmitPush(r0);
3577 Result arg_count = allocator_->Allocate(r0); 3577 Result arg_count = allocator_->Allocate(r0);
3578 ASSERT(arg_count.is_valid()); 3578 ASSERT(arg_count.is_valid());
3579 __ mov(arg_count.reg(), Operand(0)); // not counting receiver 3579 __ mov(arg_count.reg(), Operand(0)); // not counting receiver
3580 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1); 3580 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1);
3581 3581
3582 continue_label.Jump(); 3582 continue_label.Jump();
3583 smi_label.Bind(); 3583 smi_label.Bind();
3584 __ mvn(r0, Operand(r0)); 3584 __ mvn(r0, Operand(r0));
3585 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag 3585 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag
3586 continue_label.Bind(); 3586 continue_label.Bind();
3587 break; 3587 break;
3588 } 3588 }
3589 3589
3590 case Token::VOID: 3590 case Token::VOID:
3591 // since the stack top is cached in r0, popping and then 3591 // since the stack top is cached in r0, popping and then
3592 // pushing a value can be done by just writing to r0. 3592 // pushing a value can be done by just writing to r0.
3593 __ mov(r0, Operand(Factory::undefined_value())); 3593 __ mov(r0, Operand(Factory::undefined_value()));
3594 break; 3594 break;
3595 3595
3596 case Token::ADD: { 3596 case Token::ADD: {
3597 // Smi check. 3597 // Smi check.
3598 JumpTarget continue_label(this); 3598 JumpTarget continue_label;
3599 __ tst(r0, Operand(kSmiTagMask)); 3599 __ tst(r0, Operand(kSmiTagMask));
3600 continue_label.Branch(eq); 3600 continue_label.Branch(eq);
3601 frame_->EmitPush(r0); 3601 frame_->EmitPush(r0);
3602 Result arg_count = allocator_->Allocate(r0); 3602 Result arg_count = allocator_->Allocate(r0);
3603 ASSERT(arg_count.is_valid()); 3603 ASSERT(arg_count.is_valid());
3604 __ mov(arg_count.reg(), Operand(0)); // not counting receiver 3604 __ mov(arg_count.reg(), Operand(0)); // not counting receiver
3605 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); 3605 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1);
3606 continue_label.Bind(); 3606 continue_label.Bind();
3607 break; 3607 break;
3608 } 3608 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3642 if (!is_postfix) { 3642 if (!is_postfix) {
3643 __ mov(r0, Operand(Smi::FromInt(0))); 3643 __ mov(r0, Operand(Smi::FromInt(0)));
3644 frame_->EmitPush(r0); 3644 frame_->EmitPush(r0);
3645 } 3645 }
3646 ASSERT(frame_->height() == original_height + 1); 3646 ASSERT(frame_->height() == original_height + 1);
3647 return; 3647 return;
3648 } 3648 }
3649 target.GetValueAndSpill(NOT_INSIDE_TYPEOF); 3649 target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
3650 frame_->EmitPop(r0); 3650 frame_->EmitPop(r0);
3651 3651
3652 JumpTarget slow(this); 3652 JumpTarget slow;
3653 JumpTarget exit(this); 3653 JumpTarget exit;
3654 3654
3655 // Load the value (1) into register r1. 3655 // Load the value (1) into register r1.
3656 __ mov(r1, Operand(Smi::FromInt(1))); 3656 __ mov(r1, Operand(Smi::FromInt(1)));
3657 3657
3658 // Check for smi operand. 3658 // Check for smi operand.
3659 __ tst(r0, Operand(kSmiTagMask)); 3659 __ tst(r0, Operand(kSmiTagMask));
3660 slow.Branch(ne); 3660 slow.Branch(ne);
3661 3661
3662 // Postfix: Store the old value as the result. 3662 // Postfix: Store the old value as the result.
3663 if (is_postfix) { 3663 if (is_postfix) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
3732 // produced by a && or || operator is not necessarily a boolean. 3732 // produced by a && or || operator is not necessarily a boolean.
3733 3733
3734 // NOTE: If the left hand side produces a materialized value (not in 3734 // NOTE: If the left hand side produces a materialized value (not in
3735 // the CC register), we force the right hand side to do the 3735 // the CC register), we force the right hand side to do the
3736 // same. This is necessary because we may have to branch to the exit 3736 // same. This is necessary because we may have to branch to the exit
3737 // after evaluating the left hand side (due to the shortcut 3737 // after evaluating the left hand side (due to the shortcut
3738 // semantics), but the compiler must (statically) know if the result 3738 // semantics), but the compiler must (statically) know if the result
3739 // of compiling the binary operation is materialized or not. 3739 // of compiling the binary operation is materialized or not.
3740 3740
3741 if (op == Token::AND) { 3741 if (op == Token::AND) {
3742 JumpTarget is_true(this); 3742 JumpTarget is_true;
3743 LoadConditionAndSpill(node->left(), 3743 LoadConditionAndSpill(node->left(),
3744 NOT_INSIDE_TYPEOF, 3744 NOT_INSIDE_TYPEOF,
3745 &is_true, 3745 &is_true,
3746 false_target(), 3746 false_target(),
3747 false); 3747 false);
3748 if (has_cc()) { 3748 if (has_cc()) {
3749 Branch(false, false_target()); 3749 Branch(false, false_target());
3750 3750
3751 // Evaluate right side expression. 3751 // Evaluate right side expression.
3752 is_true.Bind(); 3752 is_true.Bind();
3753 LoadConditionAndSpill(node->right(), 3753 LoadConditionAndSpill(node->right(),
3754 NOT_INSIDE_TYPEOF, 3754 NOT_INSIDE_TYPEOF,
3755 true_target(), 3755 true_target(),
3756 false_target(), 3756 false_target(),
3757 false); 3757 false);
3758 3758
3759 } else { 3759 } else {
3760 JumpTarget pop_and_continue(this); 3760 JumpTarget pop_and_continue;
3761 JumpTarget exit(this); 3761 JumpTarget exit;
3762 3762
3763 __ ldr(r0, frame_->Top()); // dup the stack top 3763 __ ldr(r0, frame_->Top()); // dup the stack top
3764 frame_->EmitPush(r0); 3764 frame_->EmitPush(r0);
3765 // Avoid popping the result if it converts to 'false' using the 3765 // Avoid popping the result if it converts to 'false' using the
3766 // standard ToBoolean() conversion as described in ECMA-262, 3766 // standard ToBoolean() conversion as described in ECMA-262,
3767 // section 9.2, page 30. 3767 // section 9.2, page 30.
3768 ToBoolean(&pop_and_continue, &exit); 3768 ToBoolean(&pop_and_continue, &exit);
3769 Branch(false, &exit); 3769 Branch(false, &exit);
3770 3770
3771 // Pop the result of evaluating the first part. 3771 // Pop the result of evaluating the first part.
3772 pop_and_continue.Bind(); 3772 pop_and_continue.Bind();
3773 frame_->EmitPop(r0); 3773 frame_->EmitPop(r0);
3774 3774
3775 // Evaluate right side expression. 3775 // Evaluate right side expression.
3776 is_true.Bind(); 3776 is_true.Bind();
3777 LoadAndSpill(node->right()); 3777 LoadAndSpill(node->right());
3778 3778
3779 // Exit (always with a materialized value). 3779 // Exit (always with a materialized value).
3780 exit.Bind(); 3780 exit.Bind();
3781 } 3781 }
3782 3782
3783 } else if (op == Token::OR) { 3783 } else if (op == Token::OR) {
3784 JumpTarget is_false(this); 3784 JumpTarget is_false;
3785 LoadConditionAndSpill(node->left(), 3785 LoadConditionAndSpill(node->left(),
3786 NOT_INSIDE_TYPEOF, 3786 NOT_INSIDE_TYPEOF,
3787 true_target(), 3787 true_target(),
3788 &is_false, 3788 &is_false,
3789 false); 3789 false);
3790 if (has_cc()) { 3790 if (has_cc()) {
3791 Branch(true, true_target()); 3791 Branch(true, true_target());
3792 3792
3793 // Evaluate right side expression. 3793 // Evaluate right side expression.
3794 is_false.Bind(); 3794 is_false.Bind();
3795 LoadConditionAndSpill(node->right(), 3795 LoadConditionAndSpill(node->right(),
3796 NOT_INSIDE_TYPEOF, 3796 NOT_INSIDE_TYPEOF,
3797 true_target(), 3797 true_target(),
3798 false_target(), 3798 false_target(),
3799 false); 3799 false);
3800 3800
3801 } else { 3801 } else {
3802 JumpTarget pop_and_continue(this); 3802 JumpTarget pop_and_continue;
3803 JumpTarget exit(this); 3803 JumpTarget exit;
3804 3804
3805 __ ldr(r0, frame_->Top()); 3805 __ ldr(r0, frame_->Top());
3806 frame_->EmitPush(r0); 3806 frame_->EmitPush(r0);
3807 // Avoid popping the result if it converts to 'true' using the 3807 // Avoid popping the result if it converts to 'true' using the
3808 // standard ToBoolean() conversion as described in ECMA-262, 3808 // standard ToBoolean() conversion as described in ECMA-262,
3809 // section 9.2, page 30. 3809 // section 9.2, page 30.
3810 ToBoolean(&exit, &pop_and_continue); 3810 ToBoolean(&exit, &pop_and_continue);
3811 Branch(true, &exit); 3811 Branch(true, &exit);
3812 3812
3813 // Pop the result of evaluating the first part. 3813 // Pop the result of evaluating the first part.
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
4234 } else { 4234 } else {
4235 frame->CallRuntime(Runtime::kStoreContextSlot, 3); 4235 frame->CallRuntime(Runtime::kStoreContextSlot, 3);
4236 } 4236 }
4237 // Storing a variable must keep the (new) value on the expression 4237 // Storing a variable must keep the (new) value on the expression
4238 // stack. This is necessary for compiling assignment expressions. 4238 // stack. This is necessary for compiling assignment expressions.
4239 frame->EmitPush(r0); 4239 frame->EmitPush(r0);
4240 4240
4241 } else { 4241 } else {
4242 ASSERT(!slot->var()->is_dynamic()); 4242 ASSERT(!slot->var()->is_dynamic());
4243 4243
4244 JumpTarget exit(cgen_); 4244 JumpTarget exit;
4245 if (init_state == CONST_INIT) { 4245 if (init_state == CONST_INIT) {
4246 ASSERT(slot->var()->mode() == Variable::CONST); 4246 ASSERT(slot->var()->mode() == Variable::CONST);
4247 // Only the first const initialization must be executed (the slot 4247 // Only the first const initialization must be executed (the slot
4248 // still contains 'the hole' value). When the assignment is 4248 // still contains 'the hole' value). When the assignment is
4249 // executed, the code is identical to a normal store (see below). 4249 // executed, the code is identical to a normal store (see below).
4250 Comment cmnt(masm, "[ Init const"); 4250 Comment cmnt(masm, "[ Init const");
4251 __ ldr(r2, cgen_->SlotOperand(slot, r2)); 4251 __ ldr(r2, cgen_->SlotOperand(slot, r2));
4252 __ cmp(r2, Operand(Factory::the_hole_value())); 4252 __ cmp(r2, Operand(Factory::the_hole_value()));
4253 exit.Branch(ne); 4253 exit.Branch(ne);
4254 } 4254 }
(...skipping 925 matching lines...) Expand 10 before | Expand all | Expand 10 after
5180 __ mov(r2, Operand(0)); 5180 __ mov(r2, Operand(0));
5181 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 5181 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
5182 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), 5182 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
5183 RelocInfo::CODE_TARGET); 5183 RelocInfo::CODE_TARGET);
5184 } 5184 }
5185 5185
5186 5186
5187 #undef __ 5187 #undef __
5188 5188
5189 } } // namespace v8::internal 5189 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/arm/jump-target-arm.cc » ('j') | src/jump-target.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698