OLD | NEW |
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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 | 96 |
97 #define __ ACCESS_MASM(masm_) | 97 #define __ ACCESS_MASM(masm_) |
98 | 98 |
99 | 99 |
100 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { | 100 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { |
101 UNIMPLEMENTED(); | 101 UNIMPLEMENTED(); |
102 } | 102 } |
103 | 103 |
104 void CodeGenerator::TestCodeGenerator() { | 104 void CodeGenerator::TestCodeGenerator() { |
105 // Compile a function from a string, and run it. | 105 // Compile a function from a string, and run it. |
| 106 |
| 107 // Set flags appropriately for this stage of implementation. |
| 108 // TODO(X64): Make ic and lazy compilation work, and stop disabling them. |
| 109 // These settings stick - remove them when we don't want them anymore. |
| 110 #ifdef DEBUG |
| 111 FLAG_print_builtin_source = true; |
| 112 FLAG_print_builtin_ast = true; |
| 113 #endif |
| 114 FLAG_use_ic = false; |
| 115 FLAG_lazy = false; |
| 116 |
106 Handle<JSFunction> test_function = Compiler::Compile( | 117 Handle<JSFunction> test_function = Compiler::Compile( |
107 Factory::NewStringFromAscii(CStrVector( | 118 Factory::NewStringFromAscii(CStrVector( |
108 "39;" | 119 "// Put all code in anonymous function to avoid global scope.\n" |
109 "(function(){" | 120 "(function(){" |
110 "function foo(x, y){var w; y = x; x = w; w = y; y = x; return w;};" | 121 " function test_if_then_else(x, y, z){" |
111 "function bar(x, y, zee){return zee;};" | 122 " if (x) {" |
112 "foo(2,3);" | 123 " x = y;" |
113 "return foo(bar(foo(1,3), 42, 47), foo( -25.3, 2));" | 124 " } else {" |
| 125 " x = z;" |
| 126 " }" |
| 127 " return x;" |
| 128 " }" |
| 129 " function test_local_variables(x, y){" |
| 130 " var w; y = x; x = w; w = y; y = x; return w;" |
| 131 " };" |
| 132 " test_local_variables(2,3);" |
| 133 " function test_nesting_calls(x, y, zee){return zee;};" |
| 134 " test_local_variables(" |
| 135 " test_nesting_calls(test_local_variables(1,3), 42, 47)," |
| 136 " test_local_variables(-25.3, 2));" |
| 137 " return test_if_then_else(1, 47, 39);" |
114 "})()")), | 138 "})()")), |
115 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), | 139 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), |
116 0, | 140 0, |
117 0, | 141 0, |
118 NULL, | 142 NULL, |
119 NULL); | 143 NULL); |
120 | 144 |
121 Code* code_object = test_function->code(); // Local for debugging ease. | 145 Code* code_object = test_function->code(); // Local for debugging ease. |
122 USE(code_object); | 146 USE(code_object); |
123 | 147 |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 Load(expression); | 434 Load(expression); |
411 // Remove the lingering expression result from the top of stack. | 435 // Remove the lingering expression result from the top of stack. |
412 frame_->Drop(); | 436 frame_->Drop(); |
413 } | 437 } |
414 | 438 |
415 | 439 |
416 void CodeGenerator::VisitEmptyStatement(EmptyStatement* a) { | 440 void CodeGenerator::VisitEmptyStatement(EmptyStatement* a) { |
417 UNIMPLEMENTED(); | 441 UNIMPLEMENTED(); |
418 } | 442 } |
419 | 443 |
420 void CodeGenerator::VisitIfStatement(IfStatement* a) { | 444 |
421 UNIMPLEMENTED(); | 445 void CodeGenerator::VisitIfStatement(IfStatement* node) { |
| 446 ASSERT(!in_spilled_code()); |
| 447 Comment cmnt(masm_, "[ IfStatement"); |
| 448 // Generate different code depending on which parts of the if statement |
| 449 // are present or not. |
| 450 bool has_then_stm = node->HasThenStatement(); |
| 451 bool has_else_stm = node->HasElseStatement(); |
| 452 |
| 453 CodeForStatementPosition(node); |
| 454 JumpTarget exit; |
| 455 if (has_then_stm && has_else_stm) { |
| 456 JumpTarget then; |
| 457 JumpTarget else_; |
| 458 ControlDestination dest(&then, &else_, true); |
| 459 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); |
| 460 |
| 461 if (dest.false_was_fall_through()) { |
| 462 // The else target was bound, so we compile the else part first. |
| 463 Visit(node->else_statement()); |
| 464 |
| 465 // We may have dangling jumps to the then part. |
| 466 if (then.is_linked()) { |
| 467 if (has_valid_frame()) exit.Jump(); |
| 468 then.Bind(); |
| 469 Visit(node->then_statement()); |
| 470 } |
| 471 } else { |
| 472 // The then target was bound, so we compile the then part first. |
| 473 Visit(node->then_statement()); |
| 474 |
| 475 if (else_.is_linked()) { |
| 476 if (has_valid_frame()) exit.Jump(); |
| 477 else_.Bind(); |
| 478 Visit(node->else_statement()); |
| 479 } |
| 480 } |
| 481 |
| 482 } else if (has_then_stm) { |
| 483 ASSERT(!has_else_stm); |
| 484 JumpTarget then; |
| 485 ControlDestination dest(&then, &exit, true); |
| 486 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); |
| 487 |
| 488 if (dest.false_was_fall_through()) { |
| 489 // The exit label was bound. We may have dangling jumps to the |
| 490 // then part. |
| 491 if (then.is_linked()) { |
| 492 exit.Unuse(); |
| 493 exit.Jump(); |
| 494 then.Bind(); |
| 495 Visit(node->then_statement()); |
| 496 } |
| 497 } else { |
| 498 // The then label was bound. |
| 499 Visit(node->then_statement()); |
| 500 } |
| 501 |
| 502 } else if (has_else_stm) { |
| 503 ASSERT(!has_then_stm); |
| 504 JumpTarget else_; |
| 505 ControlDestination dest(&exit, &else_, false); |
| 506 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); |
| 507 |
| 508 if (dest.true_was_fall_through()) { |
| 509 // The exit label was bound. We may have dangling jumps to the |
| 510 // else part. |
| 511 if (else_.is_linked()) { |
| 512 exit.Unuse(); |
| 513 exit.Jump(); |
| 514 else_.Bind(); |
| 515 Visit(node->else_statement()); |
| 516 } |
| 517 } else { |
| 518 // The else label was bound. |
| 519 Visit(node->else_statement()); |
| 520 } |
| 521 |
| 522 } else { |
| 523 ASSERT(!has_then_stm && !has_else_stm); |
| 524 // We only care about the condition's side effects (not its value |
| 525 // or control flow effect). LoadCondition is called without |
| 526 // forcing control flow. |
| 527 ControlDestination dest(&exit, &exit, true); |
| 528 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, false); |
| 529 if (!dest.is_used()) { |
| 530 // We got a value on the frame rather than (or in addition to) |
| 531 // control flow. |
| 532 frame_->Drop(); |
| 533 } |
| 534 } |
| 535 |
| 536 if (exit.is_linked()) { |
| 537 exit.Bind(); |
| 538 } |
422 } | 539 } |
423 | 540 |
| 541 |
424 void CodeGenerator::VisitContinueStatement(ContinueStatement* a) { | 542 void CodeGenerator::VisitContinueStatement(ContinueStatement* a) { |
425 UNIMPLEMENTED(); | 543 UNIMPLEMENTED(); |
426 } | 544 } |
427 | 545 |
428 void CodeGenerator::VisitBreakStatement(BreakStatement* a) { | 546 void CodeGenerator::VisitBreakStatement(BreakStatement* a) { |
429 UNIMPLEMENTED(); | 547 UNIMPLEMENTED(); |
430 } | 548 } |
431 | 549 |
432 | 550 |
433 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 551 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 if (HasStackOverflow() && | 1104 if (HasStackOverflow() && |
987 !dest->is_used() && | 1105 !dest->is_used() && |
988 frame_->height() == original_height) { | 1106 frame_->height() == original_height) { |
989 dest->Goto(true); | 1107 dest->Goto(true); |
990 } | 1108 } |
991 } | 1109 } |
992 | 1110 |
993 if (force_control && !dest->is_used()) { | 1111 if (force_control && !dest->is_used()) { |
994 // Convert the TOS value into flow to the control destination. | 1112 // Convert the TOS value into flow to the control destination. |
995 // TODO(X64): Make control flow to control destinations work. | 1113 // TODO(X64): Make control flow to control destinations work. |
996 // ToBoolean(dest); | 1114 ToBoolean(dest); |
997 } | 1115 } |
998 | 1116 |
999 ASSERT(!(force_control && !dest->is_used())); | 1117 ASSERT(!(force_control && !dest->is_used())); |
1000 ASSERT(dest->is_used() || frame_->height() == original_height + 1); | 1118 ASSERT(dest->is_used() || frame_->height() == original_height + 1); |
1001 } | 1119 } |
1002 | 1120 |
1003 | 1121 |
| 1122 class ToBooleanStub: public CodeStub { |
| 1123 public: |
| 1124 ToBooleanStub() { } |
| 1125 |
| 1126 void Generate(MacroAssembler* masm); |
| 1127 |
| 1128 private: |
| 1129 Major MajorKey() { return ToBoolean; } |
| 1130 int MinorKey() { return 0; } |
| 1131 }; |
| 1132 |
| 1133 |
| 1134 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and |
| 1135 // convert it to a boolean in the condition code register or jump to |
| 1136 // 'false_target'/'true_target' as appropriate. |
| 1137 void CodeGenerator::ToBoolean(ControlDestination* dest) { |
| 1138 Comment cmnt(masm_, "[ ToBoolean"); |
| 1139 |
| 1140 // The value to convert should be popped from the frame. |
| 1141 Result value = frame_->Pop(); |
| 1142 value.ToRegister(); |
| 1143 // Fast case checks. |
| 1144 |
| 1145 // 'false' => false. |
| 1146 __ movq(kScratchRegister, Factory::false_value(), RelocInfo::EMBEDDED_OBJECT); |
| 1147 __ cmpq(value.reg(), kScratchRegister); |
| 1148 dest->false_target()->Branch(equal); |
| 1149 |
| 1150 // 'true' => true. |
| 1151 __ movq(kScratchRegister, Factory::true_value(), RelocInfo::EMBEDDED_OBJECT); |
| 1152 __ cmpq(value.reg(), kScratchRegister); |
| 1153 dest->true_target()->Branch(equal); |
| 1154 |
| 1155 // 'undefined' => false. |
| 1156 __ movq(kScratchRegister, |
| 1157 Factory::undefined_value(), |
| 1158 RelocInfo::EMBEDDED_OBJECT); |
| 1159 __ cmpq(value.reg(), kScratchRegister); |
| 1160 dest->false_target()->Branch(equal); |
| 1161 |
| 1162 // Smi => false iff zero. |
| 1163 ASSERT(kSmiTag == 0); |
| 1164 __ testq(value.reg(), value.reg()); |
| 1165 dest->false_target()->Branch(zero); |
| 1166 __ testq(value.reg(), Immediate(kSmiTagMask)); |
| 1167 dest->true_target()->Branch(zero); |
| 1168 |
| 1169 // Call the stub for all other cases. |
| 1170 frame_->Push(&value); // Undo the Pop() from above. |
| 1171 ToBooleanStub stub; |
| 1172 Result temp = frame_->CallStub(&stub, 1); |
| 1173 // Convert the result to a condition code. |
| 1174 __ testq(temp.reg(), temp.reg()); |
| 1175 temp.Unuse(); |
| 1176 dest->Split(not_equal); |
| 1177 } |
| 1178 |
| 1179 |
1004 void CodeGenerator::LoadUnsafeSmi(Register target, Handle<Object> value) { | 1180 void CodeGenerator::LoadUnsafeSmi(Register target, Handle<Object> value) { |
1005 UNIMPLEMENTED(); | 1181 UNIMPLEMENTED(); |
1006 // TODO(X64): Implement security policy for loads of smis. | 1182 // TODO(X64): Implement security policy for loads of smis. |
1007 } | 1183 } |
1008 | 1184 |
1009 | 1185 |
1010 bool CodeGenerator::IsUnsafeSmi(Handle<Object> value) { | 1186 bool CodeGenerator::IsUnsafeSmi(Handle<Object> value) { |
1011 return false; | 1187 return false; |
1012 } | 1188 } |
1013 | 1189 |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1519 #undef __ | 1695 #undef __ |
1520 | 1696 |
1521 // End of CodeGenerator implementation. | 1697 // End of CodeGenerator implementation. |
1522 | 1698 |
1523 // ----------------------------------------------------------------------------- | 1699 // ----------------------------------------------------------------------------- |
1524 // Implementation of stubs. | 1700 // Implementation of stubs. |
1525 | 1701 |
1526 // Stub classes have public member named masm, not masm_. | 1702 // Stub classes have public member named masm, not masm_. |
1527 #define __ ACCESS_MASM(masm) | 1703 #define __ ACCESS_MASM(masm) |
1528 | 1704 |
1529 class ToBooleanStub: public CodeStub { | |
1530 public: | |
1531 ToBooleanStub() { } | |
1532 | |
1533 void Generate(MacroAssembler* masm); | |
1534 | |
1535 private: | |
1536 Major MajorKey() { return ToBoolean; } | |
1537 int MinorKey() { return 0; } | |
1538 }; | |
1539 | |
1540 | |
1541 void ToBooleanStub::Generate(MacroAssembler* masm) { | 1705 void ToBooleanStub::Generate(MacroAssembler* masm) { |
1542 Label false_result, true_result, not_string; | 1706 Label false_result, true_result, not_string; |
1543 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | 1707 __ movq(rax, Operand(rsp, 1 * kPointerSize)); |
1544 | 1708 |
1545 // 'null' => false. | 1709 // 'null' => false. |
1546 __ movq(kScratchRegister, Factory::null_value(), RelocInfo::EMBEDDED_OBJECT); | 1710 __ movq(kScratchRegister, Factory::null_value(), RelocInfo::EMBEDDED_OBJECT); |
1547 __ cmpq(rax, kScratchRegister); | 1711 __ cmpq(rax, kScratchRegister); |
1548 __ j(equal, &false_result); | 1712 __ j(equal, &false_result); |
1549 | 1713 |
1550 // Get the map and type of the heap object. | 1714 // Get the map and type of the heap object. |
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2391 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers | 2555 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers |
2392 | 2556 |
2393 // Restore frame pointer and return. | 2557 // Restore frame pointer and return. |
2394 __ pop(rbp); | 2558 __ pop(rbp); |
2395 __ ret(0); | 2559 __ ret(0); |
2396 } | 2560 } |
2397 | 2561 |
2398 #undef __ | 2562 #undef __ |
2399 | 2563 |
2400 } } // namespace v8::internal | 2564 } } // namespace v8::internal |
OLD | NEW |