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

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

Issue 362004: Remove the typeof state threaded through the code generator. It was... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 1 month 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/x64/codegen-x64.h ('k') | test/mjsunit/eval-typeof-non-existing.js » ('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 2009 the V8 project authors. All rights reserved. 1 // Copyright 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 } 67 }
68 } 68 }
69 } 69 }
70 70
71 71
72 // ------------------------------------------------------------------------- 72 // -------------------------------------------------------------------------
73 // CodeGenState implementation. 73 // CodeGenState implementation.
74 74
75 CodeGenState::CodeGenState(CodeGenerator* owner) 75 CodeGenState::CodeGenState(CodeGenerator* owner)
76 : owner_(owner), 76 : owner_(owner),
77 typeof_state_(NOT_INSIDE_TYPEOF),
78 destination_(NULL), 77 destination_(NULL),
79 previous_(NULL) { 78 previous_(NULL) {
80 owner_->set_state(this); 79 owner_->set_state(this);
81 } 80 }
82 81
83 82
84 CodeGenState::CodeGenState(CodeGenerator* owner, 83 CodeGenState::CodeGenState(CodeGenerator* owner,
85 TypeofState typeof_state,
86 ControlDestination* destination) 84 ControlDestination* destination)
87 : owner_(owner), 85 : owner_(owner),
88 typeof_state_(typeof_state),
89 destination_(destination), 86 destination_(destination),
90 previous_(owner->state()) { 87 previous_(owner->state()) {
91 owner_->set_state(this); 88 owner_->set_state(this);
92 } 89 }
93 90
94 91
95 CodeGenState::~CodeGenState() { 92 CodeGenState::~CodeGenState() {
96 ASSERT(owner_->state() == this); 93 ASSERT(owner_->state() == this);
97 owner_->set_state(previous_); 94 owner_->set_state(previous_);
98 } 95 }
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 VariableProxy* arguments, 645 VariableProxy* arguments,
649 int position) { 646 int position) {
650 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); 647 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION);
651 ASSERT(arguments->IsArguments()); 648 ASSERT(arguments->IsArguments());
652 649
653 JumpTarget slow, done; 650 JumpTarget slow, done;
654 651
655 // Load the apply function onto the stack. This will usually 652 // Load the apply function onto the stack. This will usually
656 // give us a megamorphic load site. Not super, but it works. 653 // give us a megamorphic load site. Not super, but it works.
657 Reference ref(this, apply); 654 Reference ref(this, apply);
658 ref.GetValue(NOT_INSIDE_TYPEOF); 655 ref.GetValue();
659 ASSERT(ref.type() == Reference::NAMED); 656 ASSERT(ref.type() == Reference::NAMED);
660 657
661 // Load the receiver and the existing arguments object onto the 658 // Load the receiver and the existing arguments object onto the
662 // expression stack. Avoid allocating the arguments object here. 659 // expression stack. Avoid allocating the arguments object here.
663 Load(receiver); 660 Load(receiver);
664 LoadFromSlot(scope_->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); 661 LoadFromSlot(scope_->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
665 662
666 // Emit the source position information after having loaded the 663 // Emit the source position information after having loaded the
667 // receiver and the arguments. 664 // receiver and the arguments.
668 CodeForSourcePosition(position); 665 CodeForSourcePosition(position);
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 // are present or not. 970 // are present or not.
974 bool has_then_stm = node->HasThenStatement(); 971 bool has_then_stm = node->HasThenStatement();
975 bool has_else_stm = node->HasElseStatement(); 972 bool has_else_stm = node->HasElseStatement();
976 973
977 CodeForStatementPosition(node); 974 CodeForStatementPosition(node);
978 JumpTarget exit; 975 JumpTarget exit;
979 if (has_then_stm && has_else_stm) { 976 if (has_then_stm && has_else_stm) {
980 JumpTarget then; 977 JumpTarget then;
981 JumpTarget else_; 978 JumpTarget else_;
982 ControlDestination dest(&then, &else_, true); 979 ControlDestination dest(&then, &else_, true);
983 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 980 LoadCondition(node->condition(), &dest, true);
984 981
985 if (dest.false_was_fall_through()) { 982 if (dest.false_was_fall_through()) {
986 // The else target was bound, so we compile the else part first. 983 // The else target was bound, so we compile the else part first.
987 Visit(node->else_statement()); 984 Visit(node->else_statement());
988 985
989 // We may have dangling jumps to the then part. 986 // We may have dangling jumps to the then part.
990 if (then.is_linked()) { 987 if (then.is_linked()) {
991 if (has_valid_frame()) exit.Jump(); 988 if (has_valid_frame()) exit.Jump();
992 then.Bind(); 989 then.Bind();
993 Visit(node->then_statement()); 990 Visit(node->then_statement());
994 } 991 }
995 } else { 992 } else {
996 // The then target was bound, so we compile the then part first. 993 // The then target was bound, so we compile the then part first.
997 Visit(node->then_statement()); 994 Visit(node->then_statement());
998 995
999 if (else_.is_linked()) { 996 if (else_.is_linked()) {
1000 if (has_valid_frame()) exit.Jump(); 997 if (has_valid_frame()) exit.Jump();
1001 else_.Bind(); 998 else_.Bind();
1002 Visit(node->else_statement()); 999 Visit(node->else_statement());
1003 } 1000 }
1004 } 1001 }
1005 1002
1006 } else if (has_then_stm) { 1003 } else if (has_then_stm) {
1007 ASSERT(!has_else_stm); 1004 ASSERT(!has_else_stm);
1008 JumpTarget then; 1005 JumpTarget then;
1009 ControlDestination dest(&then, &exit, true); 1006 ControlDestination dest(&then, &exit, true);
1010 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 1007 LoadCondition(node->condition(), &dest, true);
1011 1008
1012 if (dest.false_was_fall_through()) { 1009 if (dest.false_was_fall_through()) {
1013 // The exit label was bound. We may have dangling jumps to the 1010 // The exit label was bound. We may have dangling jumps to the
1014 // then part. 1011 // then part.
1015 if (then.is_linked()) { 1012 if (then.is_linked()) {
1016 exit.Unuse(); 1013 exit.Unuse();
1017 exit.Jump(); 1014 exit.Jump();
1018 then.Bind(); 1015 then.Bind();
1019 Visit(node->then_statement()); 1016 Visit(node->then_statement());
1020 } 1017 }
1021 } else { 1018 } else {
1022 // The then label was bound. 1019 // The then label was bound.
1023 Visit(node->then_statement()); 1020 Visit(node->then_statement());
1024 } 1021 }
1025 1022
1026 } else if (has_else_stm) { 1023 } else if (has_else_stm) {
1027 ASSERT(!has_then_stm); 1024 ASSERT(!has_then_stm);
1028 JumpTarget else_; 1025 JumpTarget else_;
1029 ControlDestination dest(&exit, &else_, false); 1026 ControlDestination dest(&exit, &else_, false);
1030 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 1027 LoadCondition(node->condition(), &dest, true);
1031 1028
1032 if (dest.true_was_fall_through()) { 1029 if (dest.true_was_fall_through()) {
1033 // The exit label was bound. We may have dangling jumps to the 1030 // The exit label was bound. We may have dangling jumps to the
1034 // else part. 1031 // else part.
1035 if (else_.is_linked()) { 1032 if (else_.is_linked()) {
1036 exit.Unuse(); 1033 exit.Unuse();
1037 exit.Jump(); 1034 exit.Jump();
1038 else_.Bind(); 1035 else_.Bind();
1039 Visit(node->else_statement()); 1036 Visit(node->else_statement());
1040 } 1037 }
1041 } else { 1038 } else {
1042 // The else label was bound. 1039 // The else label was bound.
1043 Visit(node->else_statement()); 1040 Visit(node->else_statement());
1044 } 1041 }
1045 1042
1046 } else { 1043 } else {
1047 ASSERT(!has_then_stm && !has_else_stm); 1044 ASSERT(!has_then_stm && !has_else_stm);
1048 // We only care about the condition's side effects (not its value 1045 // We only care about the condition's side effects (not its value
1049 // or control flow effect). LoadCondition is called without 1046 // or control flow effect). LoadCondition is called without
1050 // forcing control flow. 1047 // forcing control flow.
1051 ControlDestination dest(&exit, &exit, true); 1048 ControlDestination dest(&exit, &exit, true);
1052 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, false); 1049 LoadCondition(node->condition(), &dest, false);
1053 if (!dest.is_used()) { 1050 if (!dest.is_used()) {
1054 // We got a value on the frame rather than (or in addition to) 1051 // We got a value on the frame rather than (or in addition to)
1055 // control flow. 1052 // control flow.
1056 frame_->Drop(); 1053 frame_->Drop();
1057 } 1054 }
1058 } 1055 }
1059 1056
1060 if (exit.is_linked()) { 1057 if (exit.is_linked()) {
1061 exit.Bind(); 1058 exit.Bind();
1062 } 1059 }
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 } 1311 }
1315 break; 1312 break;
1316 case DONT_KNOW: 1313 case DONT_KNOW:
1317 // We have to compile the test expression if it can be reached by 1314 // We have to compile the test expression if it can be reached by
1318 // control flow falling out of the body or via continue. 1315 // control flow falling out of the body or via continue.
1319 if (node->continue_target()->is_linked()) { 1316 if (node->continue_target()->is_linked()) {
1320 node->continue_target()->Bind(); 1317 node->continue_target()->Bind();
1321 } 1318 }
1322 if (has_valid_frame()) { 1319 if (has_valid_frame()) {
1323 ControlDestination dest(&body, node->break_target(), false); 1320 ControlDestination dest(&body, node->break_target(), false);
1324 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 1321 LoadCondition(node->cond(), &dest, true);
1325 } 1322 }
1326 if (node->break_target()->is_linked()) { 1323 if (node->break_target()->is_linked()) {
1327 node->break_target()->Bind(); 1324 node->break_target()->Bind();
1328 } 1325 }
1329 break; 1326 break;
1330 } 1327 }
1331 1328
1332 DecrementLoopNesting(); 1329 DecrementLoopNesting();
1333 node->continue_target()->Unuse(); 1330 node->continue_target()->Unuse();
1334 node->break_target()->Unuse(); 1331 node->break_target()->Unuse();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1371 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 1368 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1372 } else { 1369 } else {
1373 // Label the test at the top as the continue target. The body 1370 // Label the test at the top as the continue target. The body
1374 // is a forward-only target. 1371 // is a forward-only target.
1375 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); 1372 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1376 node->continue_target()->Bind(); 1373 node->continue_target()->Bind();
1377 } 1374 }
1378 // Compile the test with the body as the true target and preferred 1375 // Compile the test with the body as the true target and preferred
1379 // fall-through and with the break target as the false target. 1376 // fall-through and with the break target as the false target.
1380 ControlDestination dest(&body, node->break_target(), true); 1377 ControlDestination dest(&body, node->break_target(), true);
1381 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 1378 LoadCondition(node->cond(), &dest, true);
1382 1379
1383 if (dest.false_was_fall_through()) { 1380 if (dest.false_was_fall_through()) {
1384 // If we got the break target as fall-through, the test may have 1381 // If we got the break target as fall-through, the test may have
1385 // been unconditionally false (if there are no jumps to the 1382 // been unconditionally false (if there are no jumps to the
1386 // body). 1383 // body).
1387 if (!body.is_linked()) { 1384 if (!body.is_linked()) {
1388 DecrementLoopNesting(); 1385 DecrementLoopNesting();
1389 return; 1386 return;
1390 } 1387 }
1391 1388
(...skipping 26 matching lines...) Expand all
1418 if (test_at_bottom) { 1415 if (test_at_bottom) {
1419 // If we have chosen to recompile the test at the bottom, 1416 // If we have chosen to recompile the test at the bottom,
1420 // then it is the continue target. 1417 // then it is the continue target.
1421 if (node->continue_target()->is_linked()) { 1418 if (node->continue_target()->is_linked()) {
1422 node->continue_target()->Bind(); 1419 node->continue_target()->Bind();
1423 } 1420 }
1424 if (has_valid_frame()) { 1421 if (has_valid_frame()) {
1425 // The break target is the fall-through (body is a backward 1422 // The break target is the fall-through (body is a backward
1426 // jump from here and thus an invalid fall-through). 1423 // jump from here and thus an invalid fall-through).
1427 ControlDestination dest(&body, node->break_target(), false); 1424 ControlDestination dest(&body, node->break_target(), false);
1428 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 1425 LoadCondition(node->cond(), &dest, true);
1429 } 1426 }
1430 } else { 1427 } else {
1431 // If we have chosen not to recompile the test at the 1428 // If we have chosen not to recompile the test at the
1432 // bottom, jump back to the one at the top. 1429 // bottom, jump back to the one at the top.
1433 if (has_valid_frame()) { 1430 if (has_valid_frame()) {
1434 node->continue_target()->Jump(); 1431 node->continue_target()->Jump();
1435 } 1432 }
1436 } 1433 }
1437 break; 1434 break;
1438 case ALWAYS_FALSE: 1435 case ALWAYS_FALSE:
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 } else { 1507 } else {
1511 // We are not recompiling the test at the bottom and there is an 1508 // We are not recompiling the test at the bottom and there is an
1512 // update expression. 1509 // update expression.
1513 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 1510 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1514 loop.Bind(); 1511 loop.Bind();
1515 } 1512 }
1516 1513
1517 // Compile the test with the body as the true target and preferred 1514 // Compile the test with the body as the true target and preferred
1518 // fall-through and with the break target as the false target. 1515 // fall-through and with the break target as the false target.
1519 ControlDestination dest(&body, node->break_target(), true); 1516 ControlDestination dest(&body, node->break_target(), true);
1520 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 1517 LoadCondition(node->cond(), &dest, true);
1521 1518
1522 if (dest.false_was_fall_through()) { 1519 if (dest.false_was_fall_through()) {
1523 // If we got the break target as fall-through, the test may have 1520 // If we got the break target as fall-through, the test may have
1524 // been unconditionally false (if there are no jumps to the 1521 // been unconditionally false (if there are no jumps to the
1525 // body). 1522 // body).
1526 if (!body.is_linked()) { 1523 if (!body.is_linked()) {
1527 DecrementLoopNesting(); 1524 DecrementLoopNesting();
1528 return; 1525 return;
1529 } 1526 }
1530 1527
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1580 // was no update expression. 1577 // was no update expression.
1581 node->continue_target()->Bind(); 1578 node->continue_target()->Bind();
1582 } 1579 }
1583 // Control can reach the test at the bottom by falling out of 1580 // Control can reach the test at the bottom by falling out of
1584 // the body, by a continue in the body, or from the update 1581 // the body, by a continue in the body, or from the update
1585 // expression. 1582 // expression.
1586 if (has_valid_frame()) { 1583 if (has_valid_frame()) {
1587 // The break target is the fall-through (body is a backward 1584 // The break target is the fall-through (body is a backward
1588 // jump from here). 1585 // jump from here).
1589 ControlDestination dest(&body, node->break_target(), false); 1586 ControlDestination dest(&body, node->break_target(), false);
1590 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 1587 LoadCondition(node->cond(), &dest, true);
1591 } 1588 }
1592 } else { 1589 } else {
1593 // Otherwise, jump back to the test at the top. 1590 // Otherwise, jump back to the test at the top.
1594 if (has_valid_frame()) { 1591 if (has_valid_frame()) {
1595 if (node->next() == NULL) { 1592 if (node->next() == NULL) {
1596 node->continue_target()->Jump(); 1593 node->continue_target()->Jump();
1597 } else { 1594 } else {
1598 loop.Jump(); 1595 loop.Jump();
1599 } 1596 }
1600 } 1597 }
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after
2180 InstantiateBoilerplate(node->boilerplate()); 2177 InstantiateBoilerplate(node->boilerplate());
2181 } 2178 }
2182 2179
2183 2180
2184 void CodeGenerator::VisitConditional(Conditional* node) { 2181 void CodeGenerator::VisitConditional(Conditional* node) {
2185 Comment cmnt(masm_, "[ Conditional"); 2182 Comment cmnt(masm_, "[ Conditional");
2186 JumpTarget then; 2183 JumpTarget then;
2187 JumpTarget else_; 2184 JumpTarget else_;
2188 JumpTarget exit; 2185 JumpTarget exit;
2189 ControlDestination dest(&then, &else_, true); 2186 ControlDestination dest(&then, &else_, true);
2190 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); 2187 LoadCondition(node->condition(), &dest, true);
2191 2188
2192 if (dest.false_was_fall_through()) { 2189 if (dest.false_was_fall_through()) {
2193 // The else target was bound, so we compile the else part first. 2190 // The else target was bound, so we compile the else part first.
2194 Load(node->else_expression(), typeof_state()); 2191 Load(node->else_expression());
2195 2192
2196 if (then.is_linked()) { 2193 if (then.is_linked()) {
2197 exit.Jump(); 2194 exit.Jump();
2198 then.Bind(); 2195 then.Bind();
2199 Load(node->then_expression(), typeof_state()); 2196 Load(node->then_expression());
2200 } 2197 }
2201 } else { 2198 } else {
2202 // The then target was bound, so we compile the then part first. 2199 // The then target was bound, so we compile the then part first.
2203 Load(node->then_expression(), typeof_state()); 2200 Load(node->then_expression());
2204 2201
2205 if (else_.is_linked()) { 2202 if (else_.is_linked()) {
2206 exit.Jump(); 2203 exit.Jump();
2207 else_.Bind(); 2204 else_.Bind();
2208 Load(node->else_expression(), typeof_state()); 2205 Load(node->else_expression());
2209 } 2206 }
2210 } 2207 }
2211 2208
2212 exit.Bind(); 2209 exit.Bind();
2213 } 2210 }
2214 2211
2215 2212
2216 void CodeGenerator::VisitSlot(Slot* node) { 2213 void CodeGenerator::VisitSlot(Slot* node) {
2217 Comment cmnt(masm_, "[ Slot"); 2214 Comment cmnt(masm_, "[ Slot");
2218 LoadFromSlotCheckForArguments(node, typeof_state()); 2215 LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF);
2219 } 2216 }
2220 2217
2221 2218
2222 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2219 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
2223 Comment cmnt(masm_, "[ VariableProxy"); 2220 Comment cmnt(masm_, "[ VariableProxy");
2224 Variable* var = node->var(); 2221 Variable* var = node->var();
2225 Expression* expr = var->rewrite(); 2222 Expression* expr = var->rewrite();
2226 if (expr != NULL) { 2223 if (expr != NULL) {
2227 Visit(expr); 2224 Visit(expr);
2228 } else { 2225 } else {
2229 ASSERT(var->is_global()); 2226 ASSERT(var->is_global());
2230 Reference ref(this, node); 2227 Reference ref(this, node);
2231 ref.GetValue(typeof_state()); 2228 ref.GetValue();
2232 } 2229 }
2233 } 2230 }
2234 2231
2235 2232
2236 void CodeGenerator::VisitLiteral(Literal* node) { 2233 void CodeGenerator::VisitLiteral(Literal* node) {
2237 Comment cmnt(masm_, "[ Literal"); 2234 Comment cmnt(masm_, "[ Literal");
2238 frame_->Push(node->handle()); 2235 frame_->Push(node->handle());
2239 } 2236 }
2240 2237
2241 2238
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2612 bool overwrite_value = 2609 bool overwrite_value =
2613 (node->value()->AsBinaryOperation() != NULL && 2610 (node->value()->AsBinaryOperation() != NULL &&
2614 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 2611 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
2615 Variable* right_var = node->value()->AsVariableProxy()->AsVariable(); 2612 Variable* right_var = node->value()->AsVariableProxy()->AsVariable();
2616 // There are two cases where the target is not read in the right hand 2613 // There are two cases where the target is not read in the right hand
2617 // side, that are easy to test for: the right hand side is a literal, 2614 // side, that are easy to test for: the right hand side is a literal,
2618 // or the right hand side is a different variable. TakeValue invalidates 2615 // or the right hand side is a different variable. TakeValue invalidates
2619 // the target, with an implicit promise that it will be written to again 2616 // the target, with an implicit promise that it will be written to again
2620 // before it is read. 2617 // before it is read.
2621 if (literal != NULL || (right_var != NULL && right_var != var)) { 2618 if (literal != NULL || (right_var != NULL && right_var != var)) {
2622 target.TakeValue(NOT_INSIDE_TYPEOF); 2619 target.TakeValue();
2623 } else { 2620 } else {
2624 target.GetValue(NOT_INSIDE_TYPEOF); 2621 target.GetValue();
2625 } 2622 }
2626 Load(node->value()); 2623 Load(node->value());
2627 GenericBinaryOperation(node->binary_op(), 2624 GenericBinaryOperation(node->binary_op(),
2628 node->type(), 2625 node->type(),
2629 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); 2626 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
2630 } 2627 }
2631 2628
2632 if (var != NULL && 2629 if (var != NULL &&
2633 var->mode() == Variable::CONST && 2630 var->mode() == Variable::CONST &&
2634 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 2631 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
(...skipping 27 matching lines...) Expand all
2662 Comment cmnt(masm_, "[ Throw"); 2659 Comment cmnt(masm_, "[ Throw");
2663 Load(node->exception()); 2660 Load(node->exception());
2664 Result result = frame_->CallRuntime(Runtime::kThrow, 1); 2661 Result result = frame_->CallRuntime(Runtime::kThrow, 1);
2665 frame_->Push(&result); 2662 frame_->Push(&result);
2666 } 2663 }
2667 2664
2668 2665
2669 void CodeGenerator::VisitProperty(Property* node) { 2666 void CodeGenerator::VisitProperty(Property* node) {
2670 Comment cmnt(masm_, "[ Property"); 2667 Comment cmnt(masm_, "[ Property");
2671 Reference property(this, node); 2668 Reference property(this, node);
2672 property.GetValue(typeof_state()); 2669 property.GetValue();
2673 } 2670 }
2674 2671
2675 2672
2676 void CodeGenerator::VisitCall(Call* node) { 2673 void CodeGenerator::VisitCall(Call* node) {
2677 Comment cmnt(masm_, "[ Call"); 2674 Comment cmnt(masm_, "[ Call");
2678 2675
2679 ZoneList<Expression*>* args = node->arguments(); 2676 ZoneList<Expression*>* args = node->arguments();
2680 2677
2681 // Check if the function is a variable or a property. 2678 // Check if the function is a variable or a property.
2682 Expression* function = node->expression(); 2679 Expression* function = node->expression();
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
2848 frame_->SetElementAt(0, &result); 2845 frame_->SetElementAt(0, &result);
2849 } 2846 }
2850 2847
2851 } else { 2848 } else {
2852 // ------------------------------------------- 2849 // -------------------------------------------
2853 // JavaScript example: 'array[index](1, 2, 3)' 2850 // JavaScript example: 'array[index](1, 2, 3)'
2854 // ------------------------------------------- 2851 // -------------------------------------------
2855 2852
2856 // Load the function to call from the property through a reference. 2853 // Load the function to call from the property through a reference.
2857 Reference ref(this, property); 2854 Reference ref(this, property);
2858 ref.GetValue(NOT_INSIDE_TYPEOF); 2855 ref.GetValue();
2859 2856
2860 // Pass receiver to called function. 2857 // Pass receiver to called function.
2861 if (property->is_synthetic()) { 2858 if (property->is_synthetic()) {
2862 // Use global object as receiver. 2859 // Use global object as receiver.
2863 LoadGlobalReceiver(); 2860 LoadGlobalReceiver();
2864 } else { 2861 } else {
2865 // The reference's size is non-negative. 2862 // The reference's size is non-negative.
2866 frame_->PushElementAt(ref.size()); 2863 frame_->PushElementAt(ref.size());
2867 } 2864 }
2868 2865
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2954 frame_->SetElementAt(0, &answer); 2951 frame_->SetElementAt(0, &answer);
2955 } else { 2952 } else {
2956 // Call the C runtime function. 2953 // Call the C runtime function.
2957 Result answer = frame_->CallRuntime(function, arg_count); 2954 Result answer = frame_->CallRuntime(function, arg_count);
2958 frame_->Push(&answer); 2955 frame_->Push(&answer);
2959 } 2956 }
2960 } 2957 }
2961 2958
2962 2959
2963 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 2960 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
2964 // Note that because of NOT and an optimization in comparison of a typeof
2965 // expression to a literal string, this function can fail to leave a value
2966 // on top of the frame or in the cc register.
2967 Comment cmnt(masm_, "[ UnaryOperation"); 2961 Comment cmnt(masm_, "[ UnaryOperation");
2968 2962
2969 Token::Value op = node->op(); 2963 Token::Value op = node->op();
2970 2964
2971 if (op == Token::NOT) { 2965 if (op == Token::NOT) {
2972 // Swap the true and false targets but keep the same actual label 2966 // Swap the true and false targets but keep the same actual label
2973 // as the fall through. 2967 // as the fall through.
2974 destination()->Invert(); 2968 destination()->Invert();
2975 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, destination(), true); 2969 LoadCondition(node->expression(), destination(), true);
2976 // Swap the labels back. 2970 // Swap the labels back.
2977 destination()->Invert(); 2971 destination()->Invert();
2978 2972
2979 } else if (op == Token::DELETE) { 2973 } else if (op == Token::DELETE) {
2980 Property* property = node->expression()->AsProperty(); 2974 Property* property = node->expression()->AsProperty();
2981 if (property != NULL) { 2975 if (property != NULL) {
2982 Load(property->obj()); 2976 Load(property->obj());
2983 Load(property->key()); 2977 Load(property->key());
2984 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); 2978 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
2985 frame_->Push(&answer); 2979 frame_->Push(&answer);
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
3205 // value will be in the frame to be spilled. 3199 // value will be in the frame to be spilled.
3206 if (is_postfix) frame_->Push(Smi::FromInt(0)); 3200 if (is_postfix) frame_->Push(Smi::FromInt(0));
3207 3201
3208 { Reference target(this, node->expression()); 3202 { Reference target(this, node->expression());
3209 if (target.is_illegal()) { 3203 if (target.is_illegal()) {
3210 // Spoof the virtual frame to have the expected height (one higher 3204 // Spoof the virtual frame to have the expected height (one higher
3211 // than on entry). 3205 // than on entry).
3212 if (!is_postfix) frame_->Push(Smi::FromInt(0)); 3206 if (!is_postfix) frame_->Push(Smi::FromInt(0));
3213 return; 3207 return;
3214 } 3208 }
3215 target.TakeValue(NOT_INSIDE_TYPEOF); 3209 target.TakeValue();
3216 3210
3217 Result new_value = frame_->Pop(); 3211 Result new_value = frame_->Pop();
3218 new_value.ToRegister(); 3212 new_value.ToRegister();
3219 3213
3220 Result old_value; // Only allocated in the postfix case. 3214 Result old_value; // Only allocated in the postfix case.
3221 if (is_postfix) { 3215 if (is_postfix) {
3222 // Allocate a temporary to preserve the old value. 3216 // Allocate a temporary to preserve the old value.
3223 old_value = allocator_->Allocate(); 3217 old_value = allocator_->Allocate();
3224 ASSERT(old_value.is_valid()); 3218 ASSERT(old_value.is_valid());
3225 __ movq(old_value.reg(), new_value.reg()); 3219 __ movq(old_value.reg(), new_value.reg());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3263 3257
3264 // Postfix: drop the new value and use the old. 3258 // Postfix: drop the new value and use the old.
3265 if (is_postfix) frame_->Drop(); 3259 if (is_postfix) frame_->Drop();
3266 } 3260 }
3267 3261
3268 3262
3269 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 3263 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
3270 // TODO(X64): This code was copied verbatim from codegen-ia32. 3264 // TODO(X64): This code was copied verbatim from codegen-ia32.
3271 // Either find a reason to change it or move it to a shared location. 3265 // Either find a reason to change it or move it to a shared location.
3272 3266
3273 // Note that due to an optimization in comparison operations (typeof
3274 // compared to a string literal), we can evaluate a binary expression such
3275 // as AND or OR and not leave a value on the frame or in the cc register.
3276 Comment cmnt(masm_, "[ BinaryOperation"); 3267 Comment cmnt(masm_, "[ BinaryOperation");
3277 Token::Value op = node->op(); 3268 Token::Value op = node->op();
3278 3269
3279 // According to ECMA-262 section 11.11, page 58, the binary logical 3270 // According to ECMA-262 section 11.11, page 58, the binary logical
3280 // operators must yield the result of one of the two expressions 3271 // operators must yield the result of one of the two expressions
3281 // before any ToBoolean() conversions. This means that the value 3272 // before any ToBoolean() conversions. This means that the value
3282 // produced by a && or || operator is not necessarily a boolean. 3273 // produced by a && or || operator is not necessarily a boolean.
3283 3274
3284 // NOTE: If the left hand side produces a materialized value (not 3275 // NOTE: If the left hand side produces a materialized value (not
3285 // control flow), we force the right hand side to do the same. This 3276 // control flow), we force the right hand side to do the same. This
3286 // is necessary because we assume that if we get control flow on the 3277 // is necessary because we assume that if we get control flow on the
3287 // last path out of an expression we got it on all paths. 3278 // last path out of an expression we got it on all paths.
3288 if (op == Token::AND) { 3279 if (op == Token::AND) {
3289 JumpTarget is_true; 3280 JumpTarget is_true;
3290 ControlDestination dest(&is_true, destination()->false_target(), true); 3281 ControlDestination dest(&is_true, destination()->false_target(), true);
3291 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); 3282 LoadCondition(node->left(), &dest, false);
3292 3283
3293 if (dest.false_was_fall_through()) { 3284 if (dest.false_was_fall_through()) {
3294 // The current false target was used as the fall-through. If 3285 // The current false target was used as the fall-through. If
3295 // there are no dangling jumps to is_true then the left 3286 // there are no dangling jumps to is_true then the left
3296 // subexpression was unconditionally false. Otherwise we have 3287 // subexpression was unconditionally false. Otherwise we have
3297 // paths where we do have to evaluate the right subexpression. 3288 // paths where we do have to evaluate the right subexpression.
3298 if (is_true.is_linked()) { 3289 if (is_true.is_linked()) {
3299 // We need to compile the right subexpression. If the jump to 3290 // We need to compile the right subexpression. If the jump to
3300 // the current false target was a forward jump then we have a 3291 // the current false target was a forward jump then we have a
3301 // valid frame, we have just bound the false target, and we 3292 // valid frame, we have just bound the false target, and we
3302 // have to jump around the code for the right subexpression. 3293 // have to jump around the code for the right subexpression.
3303 if (has_valid_frame()) { 3294 if (has_valid_frame()) {
3304 destination()->false_target()->Unuse(); 3295 destination()->false_target()->Unuse();
3305 destination()->false_target()->Jump(); 3296 destination()->false_target()->Jump();
3306 } 3297 }
3307 is_true.Bind(); 3298 is_true.Bind();
3308 // The left subexpression compiled to control flow, so the 3299 // The left subexpression compiled to control flow, so the
3309 // right one is free to do so as well. 3300 // right one is free to do so as well.
3310 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 3301 LoadCondition(node->right(), destination(), false);
3311 } else { 3302 } else {
3312 // We have actually just jumped to or bound the current false 3303 // We have actually just jumped to or bound the current false
3313 // target but the current control destination is not marked as 3304 // target but the current control destination is not marked as
3314 // used. 3305 // used.
3315 destination()->Use(false); 3306 destination()->Use(false);
3316 } 3307 }
3317 3308
3318 } else if (dest.is_used()) { 3309 } else if (dest.is_used()) {
3319 // The left subexpression compiled to control flow (and is_true 3310 // The left subexpression compiled to control flow (and is_true
3320 // was just bound), so the right is free to do so as well. 3311 // was just bound), so the right is free to do so as well.
3321 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 3312 LoadCondition(node->right(), destination(), false);
3322 3313
3323 } else { 3314 } else {
3324 // We have a materialized value on the frame, so we exit with 3315 // We have a materialized value on the frame, so we exit with
3325 // one on all paths. There are possibly also jumps to is_true 3316 // one on all paths. There are possibly also jumps to is_true
3326 // from nested subexpressions. 3317 // from nested subexpressions.
3327 JumpTarget pop_and_continue; 3318 JumpTarget pop_and_continue;
3328 JumpTarget exit; 3319 JumpTarget exit;
3329 3320
3330 // Avoid popping the result if it converts to 'false' using the 3321 // Avoid popping the result if it converts to 'false' using the
3331 // standard ToBoolean() conversion as described in ECMA-262, 3322 // standard ToBoolean() conversion as described in ECMA-262,
(...skipping 12 matching lines...) Expand all
3344 is_true.Bind(); 3335 is_true.Bind();
3345 Load(node->right()); 3336 Load(node->right());
3346 3337
3347 // Exit (always with a materialized value). 3338 // Exit (always with a materialized value).
3348 exit.Bind(); 3339 exit.Bind();
3349 } 3340 }
3350 3341
3351 } else if (op == Token::OR) { 3342 } else if (op == Token::OR) {
3352 JumpTarget is_false; 3343 JumpTarget is_false;
3353 ControlDestination dest(destination()->true_target(), &is_false, false); 3344 ControlDestination dest(destination()->true_target(), &is_false, false);
3354 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); 3345 LoadCondition(node->left(), &dest, false);
3355 3346
3356 if (dest.true_was_fall_through()) { 3347 if (dest.true_was_fall_through()) {
3357 // The current true target was used as the fall-through. If 3348 // The current true target was used as the fall-through. If
3358 // there are no dangling jumps to is_false then the left 3349 // there are no dangling jumps to is_false then the left
3359 // subexpression was unconditionally true. Otherwise we have 3350 // subexpression was unconditionally true. Otherwise we have
3360 // paths where we do have to evaluate the right subexpression. 3351 // paths where we do have to evaluate the right subexpression.
3361 if (is_false.is_linked()) { 3352 if (is_false.is_linked()) {
3362 // We need to compile the right subexpression. If the jump to 3353 // We need to compile the right subexpression. If the jump to
3363 // the current true target was a forward jump then we have a 3354 // the current true target was a forward jump then we have a
3364 // valid frame, we have just bound the true target, and we 3355 // valid frame, we have just bound the true target, and we
3365 // have to jump around the code for the right subexpression. 3356 // have to jump around the code for the right subexpression.
3366 if (has_valid_frame()) { 3357 if (has_valid_frame()) {
3367 destination()->true_target()->Unuse(); 3358 destination()->true_target()->Unuse();
3368 destination()->true_target()->Jump(); 3359 destination()->true_target()->Jump();
3369 } 3360 }
3370 is_false.Bind(); 3361 is_false.Bind();
3371 // The left subexpression compiled to control flow, so the 3362 // The left subexpression compiled to control flow, so the
3372 // right one is free to do so as well. 3363 // right one is free to do so as well.
3373 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 3364 LoadCondition(node->right(), destination(), false);
3374 } else { 3365 } else {
3375 // We have just jumped to or bound the current true target but 3366 // We have just jumped to or bound the current true target but
3376 // the current control destination is not marked as used. 3367 // the current control destination is not marked as used.
3377 destination()->Use(true); 3368 destination()->Use(true);
3378 } 3369 }
3379 3370
3380 } else if (dest.is_used()) { 3371 } else if (dest.is_used()) {
3381 // The left subexpression compiled to control flow (and is_false 3372 // The left subexpression compiled to control flow (and is_false
3382 // was just bound), so the right is free to do so as well. 3373 // was just bound), so the right is free to do so as well.
3383 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); 3374 LoadCondition(node->right(), destination(), false);
3384 3375
3385 } else { 3376 } else {
3386 // We have a materialized value on the frame, so we exit with 3377 // We have a materialized value on the frame, so we exit with
3387 // one on all paths. There are possibly also jumps to is_false 3378 // one on all paths. There are possibly also jumps to is_false
3388 // from nested subexpressions. 3379 // from nested subexpressions.
3389 JumpTarget pop_and_continue; 3380 JumpTarget pop_and_continue;
3390 JumpTarget exit; 3381 JumpTarget exit;
3391 3382
3392 // Avoid popping the result if it converts to 'true' using the 3383 // Avoid popping the result if it converts to 'true' using the
3393 // standard ToBoolean() conversion as described in ECMA-262, 3384 // standard ToBoolean() conversion as described in ECMA-262,
(...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after
4094 __ movq(temp.reg(), FieldOperand(object.reg(), JSValue::kValueOffset)); 4085 __ movq(temp.reg(), FieldOperand(object.reg(), JSValue::kValueOffset));
4095 object.Unuse(); 4086 object.Unuse();
4096 frame_->SetElementAt(0, &temp); 4087 frame_->SetElementAt(0, &temp);
4097 leave.Bind(); 4088 leave.Bind();
4098 } 4089 }
4099 4090
4100 4091
4101 // ----------------------------------------------------------------------------- 4092 // -----------------------------------------------------------------------------
4102 // CodeGenerator implementation of Expressions 4093 // CodeGenerator implementation of Expressions
4103 4094
4104 void CodeGenerator::LoadAndSpill(Expression* expression, 4095 void CodeGenerator::LoadAndSpill(Expression* expression) {
4105 TypeofState typeof_state) {
4106 // TODO(x64): No architecture specific code. Move to shared location. 4096 // TODO(x64): No architecture specific code. Move to shared location.
4107 ASSERT(in_spilled_code()); 4097 ASSERT(in_spilled_code());
4108 set_in_spilled_code(false); 4098 set_in_spilled_code(false);
4109 Load(expression, typeof_state); 4099 Load(expression);
4110 frame_->SpillAll(); 4100 frame_->SpillAll();
4111 set_in_spilled_code(true); 4101 set_in_spilled_code(true);
4112 } 4102 }
4113 4103
4114 4104
4115 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 4105 void CodeGenerator::Load(Expression* expr) {
4116 #ifdef DEBUG 4106 #ifdef DEBUG
4117 int original_height = frame_->height(); 4107 int original_height = frame_->height();
4118 #endif 4108 #endif
4119 ASSERT(!in_spilled_code()); 4109 ASSERT(!in_spilled_code());
4120 JumpTarget true_target; 4110 JumpTarget true_target;
4121 JumpTarget false_target; 4111 JumpTarget false_target;
4122 ControlDestination dest(&true_target, &false_target, true); 4112 ControlDestination dest(&true_target, &false_target, true);
4123 LoadCondition(x, typeof_state, &dest, false); 4113 LoadCondition(expr, &dest, false);
4124 4114
4125 if (dest.false_was_fall_through()) { 4115 if (dest.false_was_fall_through()) {
4126 // The false target was just bound. 4116 // The false target was just bound.
4127 JumpTarget loaded; 4117 JumpTarget loaded;
4128 frame_->Push(Factory::false_value()); 4118 frame_->Push(Factory::false_value());
4129 // There may be dangling jumps to the true target. 4119 // There may be dangling jumps to the true target.
4130 if (true_target.is_linked()) { 4120 if (true_target.is_linked()) {
4131 loaded.Jump(); 4121 loaded.Jump();
4132 true_target.Bind(); 4122 true_target.Bind();
4133 frame_->Push(Factory::true_value()); 4123 frame_->Push(Factory::true_value());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4173 ASSERT(has_valid_frame()); 4163 ASSERT(has_valid_frame());
4174 ASSERT(frame_->height() == original_height + 1); 4164 ASSERT(frame_->height() == original_height + 1);
4175 } 4165 }
4176 4166
4177 4167
4178 // Emit code to load the value of an expression to the top of the 4168 // Emit code to load the value of an expression to the top of the
4179 // frame. If the expression is boolean-valued it may be compiled (or 4169 // frame. If the expression is boolean-valued it may be compiled (or
4180 // partially compiled) into control flow to the control destination. 4170 // partially compiled) into control flow to the control destination.
4181 // If force_control is true, control flow is forced. 4171 // If force_control is true, control flow is forced.
4182 void CodeGenerator::LoadCondition(Expression* x, 4172 void CodeGenerator::LoadCondition(Expression* x,
4183 TypeofState typeof_state,
4184 ControlDestination* dest, 4173 ControlDestination* dest,
4185 bool force_control) { 4174 bool force_control) {
4186 ASSERT(!in_spilled_code()); 4175 ASSERT(!in_spilled_code());
4187 int original_height = frame_->height(); 4176 int original_height = frame_->height();
4188 4177
4189 { CodeGenState new_state(this, typeof_state, dest); 4178 { CodeGenState new_state(this, dest);
4190 Visit(x); 4179 Visit(x);
4191 4180
4192 // If we hit a stack overflow, we may not have actually visited 4181 // If we hit a stack overflow, we may not have actually visited
4193 // the expression. In that case, we ensure that we have a 4182 // the expression. In that case, we ensure that we have a
4194 // valid-looking frame state because we will continue to generate 4183 // valid-looking frame state because we will continue to generate
4195 // code as we unwind the C++ stack. 4184 // code as we unwind the C++ stack.
4196 // 4185 //
4197 // It's possible to have both a stack overflow and a valid frame 4186 // It's possible to have both a stack overflow and a valid frame
4198 // state (eg, a subexpression overflowed, visiting it returned 4187 // state (eg, a subexpression overflowed, visiting it returned
4199 // with a dummied frame state, and visiting this expression 4188 // with a dummied frame state, and visiting this expression
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after
4807 if (!skip_arguments) { 4796 if (!skip_arguments) {
4808 arguments_ref.SetValue(NOT_CONST_INIT); 4797 arguments_ref.SetValue(NOT_CONST_INIT);
4809 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); 4798 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
4810 } 4799 }
4811 shadow_ref.SetValue(NOT_CONST_INIT); 4800 shadow_ref.SetValue(NOT_CONST_INIT);
4812 } 4801 }
4813 return frame_->Pop(); 4802 return frame_->Pop();
4814 } 4803 }
4815 4804
4816 4805
4817 // TODO(1241834): Get rid of this function in favor of just using Load, now 4806 void CodeGenerator::LoadTypeofExpression(Expression* expr) {
4818 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global 4807 // Special handling of identifiers as subexpressions of typeof.
4819 // variables w/o reference errors elsewhere. 4808 Variable* variable = expr->AsVariableProxy()->AsVariable();
4820 void CodeGenerator::LoadTypeofExpression(Expression* x) {
4821 Variable* variable = x->AsVariableProxy()->AsVariable();
4822 if (variable != NULL && !variable->is_this() && variable->is_global()) { 4809 if (variable != NULL && !variable->is_this() && variable->is_global()) {
4823 // NOTE: This is somewhat nasty. We force the compiler to load 4810 // For a global variable we build the property reference
4824 // the variable as if through '<global>.<variable>' to make sure we 4811 // <global>.<variable> and perform a (regular non-contextual) property
4825 // do not get reference errors. 4812 // load to make sure we do not get reference errors.
4826 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); 4813 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
4827 Literal key(variable->name()); 4814 Literal key(variable->name());
4828 // TODO(1241834): Fetch the position from the variable instead of using 4815 // TODO(1241834): Fetch the position from the variable instead of using
4829 // no position. 4816 // no position.
4830 Property property(&global, &key, RelocInfo::kNoPosition); 4817 Property property(&global, &key, RelocInfo::kNoPosition);
4831 Load(&property); 4818 Reference ref(this, &property);
4819 ref.GetValue();
4820 } else if (variable != NULL && variable->slot() != NULL) {
4821 // For a variable that rewrites to a slot, we signal it is the immediate
4822 // subexpression of a typeof.
4823 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF);
4832 } else { 4824 } else {
4833 Load(x, INSIDE_TYPEOF); 4825 // Anything else can be handled normally.
4826 Load(expr);
4834 } 4827 }
4835 } 4828 }
4836 4829
4837 4830
4838 void CodeGenerator::Comparison(Condition cc, 4831 void CodeGenerator::Comparison(Condition cc,
4839 bool strict, 4832 bool strict,
4840 ControlDestination* dest) { 4833 ControlDestination* dest) {
4841 // Strict only makes sense for equality comparisons. 4834 // Strict only makes sense for equality comparisons.
4842 ASSERT(!strict || cc == equal); 4835 ASSERT(!strict || cc == equal);
4843 4836
(...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after
5718 ASSERT(proxy->AsVariable()->is_global()); 5711 ASSERT(proxy->AsVariable()->is_global());
5719 return proxy->name(); 5712 return proxy->name();
5720 } else { 5713 } else {
5721 Literal* raw_name = property->key()->AsLiteral(); 5714 Literal* raw_name = property->key()->AsLiteral();
5722 ASSERT(raw_name != NULL); 5715 ASSERT(raw_name != NULL);
5723 return Handle<String>(String::cast(*raw_name->handle())); 5716 return Handle<String>(String::cast(*raw_name->handle()));
5724 } 5717 }
5725 } 5718 }
5726 5719
5727 5720
5728 void Reference::GetValue(TypeofState typeof_state) { 5721 void Reference::GetValue() {
5729 ASSERT(!cgen_->in_spilled_code()); 5722 ASSERT(!cgen_->in_spilled_code());
5730 ASSERT(cgen_->HasValidEntryRegisters()); 5723 ASSERT(cgen_->HasValidEntryRegisters());
5731 ASSERT(!is_illegal()); 5724 ASSERT(!is_illegal());
5732 MacroAssembler* masm = cgen_->masm(); 5725 MacroAssembler* masm = cgen_->masm();
5733 5726
5734 // Record the source position for the property load. 5727 // Record the source position for the property load.
5735 Property* property = expression_->AsProperty(); 5728 Property* property = expression_->AsProperty();
5736 if (property != NULL) { 5729 if (property != NULL) {
5737 cgen_->CodeForSourcePosition(property->position()); 5730 cgen_->CodeForSourcePosition(property->position());
5738 } 5731 }
5739 5732
5740 switch (type_) { 5733 switch (type_) {
5741 case SLOT: { 5734 case SLOT: {
5742 Comment cmnt(masm, "[ Load from Slot"); 5735 Comment cmnt(masm, "[ Load from Slot");
5743 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 5736 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
5744 ASSERT(slot != NULL); 5737 ASSERT(slot != NULL);
5745 cgen_->LoadFromSlotCheckForArguments(slot, typeof_state); 5738 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
5746 break; 5739 break;
5747 } 5740 }
5748 5741
5749 case NAMED: { 5742 case NAMED: {
5750 // TODO(1241834): Make sure that it is safe to ignore the
5751 // distinction between expressions in a typeof and not in a
5752 // typeof. If there is a chance that reference errors can be
5753 // thrown below, we must distinguish between the two kinds of
5754 // loads (typeof expression loads must not throw a reference
5755 // error).
5756 Variable* var = expression_->AsVariableProxy()->AsVariable(); 5743 Variable* var = expression_->AsVariableProxy()->AsVariable();
5757 bool is_global = var != NULL; 5744 bool is_global = var != NULL;
5758 ASSERT(!is_global || var->is_global()); 5745 ASSERT(!is_global || var->is_global());
5759 5746
5760 // Do not inline the inobject property case for loads from the global 5747 // Do not inline the inobject property case for loads from the global
5761 // object. Also do not inline for unoptimized code. This saves time 5748 // object. Also do not inline for unoptimized code. This saves time
5762 // in the code generator. Unoptimized code is toplevel code or code 5749 // in the code generator. Unoptimized code is toplevel code or code
5763 // that is not in a loop. 5750 // that is not in a loop.
5764 if (is_global || 5751 if (is_global ||
5765 cgen_->scope()->is_global_scope() || 5752 cgen_->scope()->is_global_scope() ||
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
5827 5814
5828 __ IncrementCounter(&Counters::named_load_inline, 1); 5815 __ IncrementCounter(&Counters::named_load_inline, 1);
5829 deferred->BindExit(); 5816 deferred->BindExit();
5830 cgen_->frame()->Push(&receiver); 5817 cgen_->frame()->Push(&receiver);
5831 cgen_->frame()->Push(&value); 5818 cgen_->frame()->Push(&value);
5832 } 5819 }
5833 break; 5820 break;
5834 } 5821 }
5835 5822
5836 case KEYED: { 5823 case KEYED: {
5837 // TODO(1241834): Make sure that this it is safe to ignore the
5838 // distinction between expressions in a typeof and not in a typeof.
5839 Comment cmnt(masm, "[ Load from keyed Property"); 5824 Comment cmnt(masm, "[ Load from keyed Property");
5840 Variable* var = expression_->AsVariableProxy()->AsVariable(); 5825 Variable* var = expression_->AsVariableProxy()->AsVariable();
5841 bool is_global = var != NULL; 5826 bool is_global = var != NULL;
5842 ASSERT(!is_global || var->is_global()); 5827 ASSERT(!is_global || var->is_global());
5843 5828
5844 // Inline array load code if inside of a loop. We do not know 5829 // Inline array load code if inside of a loop. We do not know
5845 // the receiver map yet, so we initially generate the code with 5830 // the receiver map yet, so we initially generate the code with
5846 // a check against an invalid map. In the inline cache code, we 5831 // a check against an invalid map. In the inline cache code, we
5847 // patch the map check if appropriate. 5832 // patch the map check if appropriate.
5848 if (cgen_->loop_nesting() > 0) { 5833 if (cgen_->loop_nesting() > 0) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
5950 } 5935 }
5951 break; 5936 break;
5952 } 5937 }
5953 5938
5954 default: 5939 default:
5955 UNREACHABLE(); 5940 UNREACHABLE();
5956 } 5941 }
5957 } 5942 }
5958 5943
5959 5944
5960 void Reference::TakeValue(TypeofState typeof_state) { 5945 void Reference::TakeValue() {
5961 // TODO(X64): This function is completely architecture independent. Move 5946 // TODO(X64): This function is completely architecture independent. Move
5962 // it somewhere shared. 5947 // it somewhere shared.
5963 5948
5964 // For non-constant frame-allocated slots, we invalidate the value in the 5949 // For non-constant frame-allocated slots, we invalidate the value in the
5965 // slot. For all others, we fall back on GetValue. 5950 // slot. For all others, we fall back on GetValue.
5966 ASSERT(!cgen_->in_spilled_code()); 5951 ASSERT(!cgen_->in_spilled_code());
5967 ASSERT(!is_illegal()); 5952 ASSERT(!is_illegal());
5968 if (type_ != SLOT) { 5953 if (type_ != SLOT) {
5969 GetValue(typeof_state); 5954 GetValue();
5970 return; 5955 return;
5971 } 5956 }
5972 5957
5973 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 5958 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
5974 ASSERT(slot != NULL); 5959 ASSERT(slot != NULL);
5975 if (slot->type() == Slot::LOOKUP || 5960 if (slot->type() == Slot::LOOKUP ||
5976 slot->type() == Slot::CONTEXT || 5961 slot->type() == Slot::CONTEXT ||
5977 slot->var()->mode() == Variable::CONST || 5962 slot->var()->mode() == Variable::CONST ||
5978 slot->is_arguments()) { 5963 slot->is_arguments()) {
5979 GetValue(typeof_state); 5964 GetValue();
5980 return; 5965 return;
5981 } 5966 }
5982 5967
5983 // Only non-constant, frame-allocated parameters and locals can reach 5968 // Only non-constant, frame-allocated parameters and locals can reach
5984 // here. Be careful not to use the optimizations for arguments 5969 // here. Be careful not to use the optimizations for arguments
5985 // object access since it may not have been initialized yet. 5970 // object access since it may not have been initialized yet.
5986 ASSERT(!slot->is_arguments()); 5971 ASSERT(!slot->is_arguments());
5987 if (slot->type() == Slot::PARAMETER) { 5972 if (slot->type() == Slot::PARAMETER) {
5988 cgen_->frame()->TakeParameterAt(slot->index()); 5973 cgen_->frame()->TakeParameterAt(slot->index());
5989 } else { 5974 } else {
(...skipping 1862 matching lines...) Expand 10 before | Expand all | Expand 10 after
7852 masm.GetCode(&desc); 7837 masm.GetCode(&desc);
7853 // Call the function from C++. 7838 // Call the function from C++.
7854 return FUNCTION_CAST<ModuloFunction>(buffer); 7839 return FUNCTION_CAST<ModuloFunction>(buffer);
7855 } 7840 }
7856 7841
7857 #endif 7842 #endif
7858 7843
7859 #undef __ 7844 #undef __
7860 7845
7861 } } // namespace v8::internal 7846 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | test/mjsunit/eval-typeof-non-existing.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698