OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 bool is_eval) | 76 bool is_eval) |
77 : is_eval_(is_eval), | 77 : is_eval_(is_eval), |
78 script_(script), | 78 script_(script), |
79 deferred_(8), | 79 deferred_(8), |
80 masm_(new MacroAssembler(NULL, buffer_size)), | 80 masm_(new MacroAssembler(NULL, buffer_size)), |
81 scope_(NULL), | 81 scope_(NULL), |
82 frame_(NULL), | 82 frame_(NULL), |
83 allocator_(NULL), | 83 allocator_(NULL), |
84 cc_reg_(al), | 84 cc_reg_(al), |
85 state_(NULL), | 85 state_(NULL), |
86 break_stack_height_(0), | |
87 function_return_is_shadowed_(false), | 86 function_return_is_shadowed_(false), |
88 in_spilled_code_(false) { | 87 in_spilled_code_(false) { |
89 } | 88 } |
90 | 89 |
91 | 90 |
92 // Calling conventions: | 91 // Calling conventions: |
93 // fp: caller's frame pointer | 92 // fp: caller's frame pointer |
94 // sp: stack pointer | 93 // sp: stack pointer |
95 // r1: called JS function | 94 // r1: called JS function |
96 // cp: callee's context | 95 // cp: callee's context |
97 | 96 |
98 void CodeGenerator::GenCode(FunctionLiteral* fun) { | 97 void CodeGenerator::GenCode(FunctionLiteral* fun) { |
99 ZoneList<Statement*>* body = fun->body(); | 98 ZoneList<Statement*>* body = fun->body(); |
100 | 99 |
101 // Initialize state. | 100 // Initialize state. |
102 ASSERT(scope_ == NULL); | 101 ASSERT(scope_ == NULL); |
103 scope_ = fun->scope(); | 102 scope_ = fun->scope(); |
104 ASSERT(allocator_ == NULL); | 103 ASSERT(allocator_ == NULL); |
105 RegisterAllocator register_allocator(this); | 104 RegisterAllocator register_allocator(this); |
106 allocator_ = ®ister_allocator; | 105 allocator_ = ®ister_allocator; |
107 ASSERT(frame_ == NULL); | 106 ASSERT(frame_ == NULL); |
108 frame_ = new VirtualFrame(this); | 107 frame_ = new VirtualFrame(this); |
109 cc_reg_ = al; | 108 cc_reg_ = al; |
110 function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL); | |
111 function_return_is_shadowed_ = false; | |
112 set_in_spilled_code(false); | 109 set_in_spilled_code(false); |
113 { | 110 { |
114 CodeGenState state(this); | 111 CodeGenState state(this); |
115 | 112 |
116 // Entry: | 113 // Entry: |
117 // Stack: receiver, arguments | 114 // Stack: receiver, arguments |
118 // lr: return address | 115 // lr: return address |
119 // fp: caller's frame pointer | 116 // fp: caller's frame pointer |
120 // sp: stack pointer | 117 // sp: stack pointer |
121 // r1: called JS function | 118 // r1: called JS function |
122 // cp: callee's context | 119 // cp: callee's context |
123 allocator_->Initialize(); | 120 allocator_->Initialize(); |
124 frame_->Enter(); | 121 frame_->Enter(); |
125 // tos: code slot | 122 // tos: code slot |
126 #ifdef DEBUG | 123 #ifdef DEBUG |
127 if (strlen(FLAG_stop_at) > 0 && | 124 if (strlen(FLAG_stop_at) > 0 && |
128 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 125 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
129 frame_->SpillAll(); | 126 frame_->SpillAll(); |
130 __ stop("stop-at"); | 127 __ stop("stop-at"); |
131 } | 128 } |
132 #endif | 129 #endif |
133 | 130 |
134 // Allocate space for locals and initialize them. | 131 // Allocate space for locals and initialize them. |
135 frame_->AllocateStackSlots(scope_->num_stack_slots()); | 132 frame_->AllocateStackSlots(scope_->num_stack_slots()); |
| 133 // Initialize the function return target after the locals are set |
| 134 // up, because it needs the expected frame height from the frame. |
| 135 function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL); |
| 136 function_return_is_shadowed_ = false; |
136 | 137 |
137 VirtualFrame::SpilledScope spilled_scope(this); | 138 VirtualFrame::SpilledScope spilled_scope(this); |
138 if (scope_->num_heap_slots() > 0) { | 139 if (scope_->num_heap_slots() > 0) { |
139 // Allocate local context. | 140 // Allocate local context. |
140 // Get outer context and create a new context based on it. | 141 // Get outer context and create a new context based on it. |
141 __ ldr(r0, frame_->Function()); | 142 __ ldr(r0, frame_->Function()); |
142 frame_->EmitPush(r0); | 143 frame_->EmitPush(r0); |
143 frame_->CallRuntime(Runtime::kNewContext, 1); // r0 holds the result | 144 frame_->CallRuntime(Runtime::kNewContext, 1); // r0 holds the result |
144 | 145 |
145 if (kDebug) { | 146 if (kDebug) { |
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1120 } | 1121 } |
1121 | 1122 |
1122 | 1123 |
1123 void CodeGenerator::VisitBlock(Block* node) { | 1124 void CodeGenerator::VisitBlock(Block* node) { |
1124 #ifdef DEBUG | 1125 #ifdef DEBUG |
1125 int original_height = frame_->height(); | 1126 int original_height = frame_->height(); |
1126 #endif | 1127 #endif |
1127 VirtualFrame::SpilledScope spilled_scope(this); | 1128 VirtualFrame::SpilledScope spilled_scope(this); |
1128 Comment cmnt(masm_, "[ Block"); | 1129 Comment cmnt(masm_, "[ Block"); |
1129 CodeForStatementPosition(node); | 1130 CodeForStatementPosition(node); |
1130 node->set_break_stack_height(break_stack_height_); | |
1131 node->break_target()->Initialize(this); | 1131 node->break_target()->Initialize(this); |
1132 VisitStatementsAndSpill(node->statements()); | 1132 VisitStatementsAndSpill(node->statements()); |
1133 if (node->break_target()->is_linked()) { | 1133 if (node->break_target()->is_linked()) { |
1134 node->break_target()->Bind(); | 1134 node->break_target()->Bind(); |
1135 } | 1135 } |
1136 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1136 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
1137 } | 1137 } |
1138 | 1138 |
1139 | 1139 |
1140 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1140 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 } | 1334 } |
1335 | 1335 |
1336 // end | 1336 // end |
1337 if (exit.is_linked()) { | 1337 if (exit.is_linked()) { |
1338 exit.Bind(); | 1338 exit.Bind(); |
1339 } | 1339 } |
1340 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1340 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
1341 } | 1341 } |
1342 | 1342 |
1343 | 1343 |
1344 void CodeGenerator::CleanStack(int num_bytes) { | |
1345 VirtualFrame::SpilledScope spilled_scope(this); | |
1346 ASSERT(num_bytes % kPointerSize == 0); | |
1347 frame_->Drop(num_bytes / kPointerSize); | |
1348 } | |
1349 | |
1350 | |
1351 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { | 1344 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { |
1352 VirtualFrame::SpilledScope spilled_scope(this); | 1345 VirtualFrame::SpilledScope spilled_scope(this); |
1353 Comment cmnt(masm_, "[ ContinueStatement"); | 1346 Comment cmnt(masm_, "[ ContinueStatement"); |
1354 CodeForStatementPosition(node); | 1347 CodeForStatementPosition(node); |
1355 CleanStack(break_stack_height_ - node->target()->break_stack_height()); | |
1356 node->target()->continue_target()->Jump(); | 1348 node->target()->continue_target()->Jump(); |
1357 } | 1349 } |
1358 | 1350 |
1359 | 1351 |
1360 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { | 1352 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { |
1361 VirtualFrame::SpilledScope spilled_scope(this); | 1353 VirtualFrame::SpilledScope spilled_scope(this); |
1362 Comment cmnt(masm_, "[ BreakStatement"); | 1354 Comment cmnt(masm_, "[ BreakStatement"); |
1363 CodeForStatementPosition(node); | 1355 CodeForStatementPosition(node); |
1364 CleanStack(break_stack_height_ - node->target()->break_stack_height()); | |
1365 node->target()->break_target()->Jump(); | 1356 node->target()->break_target()->Jump(); |
1366 } | 1357 } |
1367 | 1358 |
1368 | 1359 |
1369 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 1360 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
1370 VirtualFrame::SpilledScope spilled_scope(this); | 1361 VirtualFrame::SpilledScope spilled_scope(this); |
1371 Comment cmnt(masm_, "[ ReturnStatement"); | 1362 Comment cmnt(masm_, "[ ReturnStatement"); |
1372 | 1363 |
1373 if (function_return_is_shadowed_) { | 1364 if (function_return_is_shadowed_) { |
1374 CodeForStatementPosition(node); | 1365 CodeForStatementPosition(node); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 } | 1505 } |
1515 | 1506 |
1516 | 1507 |
1517 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | 1508 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { |
1518 #ifdef DEBUG | 1509 #ifdef DEBUG |
1519 int original_height = frame_->height(); | 1510 int original_height = frame_->height(); |
1520 #endif | 1511 #endif |
1521 VirtualFrame::SpilledScope spilled_scope(this); | 1512 VirtualFrame::SpilledScope spilled_scope(this); |
1522 Comment cmnt(masm_, "[ SwitchStatement"); | 1513 Comment cmnt(masm_, "[ SwitchStatement"); |
1523 CodeForStatementPosition(node); | 1514 CodeForStatementPosition(node); |
1524 node->set_break_stack_height(break_stack_height_); | |
1525 node->break_target()->Initialize(this); | 1515 node->break_target()->Initialize(this); |
1526 | 1516 |
1527 LoadAndSpill(node->tag()); | 1517 LoadAndSpill(node->tag()); |
1528 if (TryGenerateFastCaseSwitchStatement(node)) { | 1518 if (TryGenerateFastCaseSwitchStatement(node)) { |
1529 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1519 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
1530 return; | 1520 return; |
1531 } | 1521 } |
1532 | 1522 |
1533 JumpTarget next_test(this); | 1523 JumpTarget next_test(this); |
1534 JumpTarget fall_through(this); | 1524 JumpTarget fall_through(this); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1608 } | 1598 } |
1609 | 1599 |
1610 | 1600 |
1611 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { | 1601 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { |
1612 #ifdef DEBUG | 1602 #ifdef DEBUG |
1613 int original_height = frame_->height(); | 1603 int original_height = frame_->height(); |
1614 #endif | 1604 #endif |
1615 VirtualFrame::SpilledScope spilled_scope(this); | 1605 VirtualFrame::SpilledScope spilled_scope(this); |
1616 Comment cmnt(masm_, "[ LoopStatement"); | 1606 Comment cmnt(masm_, "[ LoopStatement"); |
1617 CodeForStatementPosition(node); | 1607 CodeForStatementPosition(node); |
1618 node->set_break_stack_height(break_stack_height_); | |
1619 node->break_target()->Initialize(this); | 1608 node->break_target()->Initialize(this); |
1620 | 1609 |
1621 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a | 1610 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a |
1622 // known result for the test expression, with no side effects. | 1611 // known result for the test expression, with no side effects. |
1623 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 1612 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; |
1624 if (node->cond() == NULL) { | 1613 if (node->cond() == NULL) { |
1625 ASSERT(node->type() == LoopStatement::FOR_LOOP); | 1614 ASSERT(node->type() == LoopStatement::FOR_LOOP); |
1626 info = ALWAYS_TRUE; | 1615 info = ALWAYS_TRUE; |
1627 } else { | 1616 } else { |
1628 Literal* lit = node->cond()->AsLiteral(); | 1617 Literal* lit = node->cond()->AsLiteral(); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1798 | 1787 |
1799 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 1788 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
1800 #ifdef DEBUG | 1789 #ifdef DEBUG |
1801 int original_height = frame_->height(); | 1790 int original_height = frame_->height(); |
1802 #endif | 1791 #endif |
1803 ASSERT(!in_spilled_code()); | 1792 ASSERT(!in_spilled_code()); |
1804 VirtualFrame::SpilledScope spilled_scope(this); | 1793 VirtualFrame::SpilledScope spilled_scope(this); |
1805 Comment cmnt(masm_, "[ ForInStatement"); | 1794 Comment cmnt(masm_, "[ ForInStatement"); |
1806 CodeForStatementPosition(node); | 1795 CodeForStatementPosition(node); |
1807 | 1796 |
1808 // We keep stuff on the stack while the body is executing. | |
1809 // Record it, so that a break/continue crossing this statement | |
1810 // can restore the stack. | |
1811 const int kForInStackSize = 5 * kPointerSize; | |
1812 break_stack_height_ += kForInStackSize; | |
1813 node->set_break_stack_height(break_stack_height_); | |
1814 node->break_target()->Initialize(this); | |
1815 node->continue_target()->Initialize(this); | |
1816 | |
1817 JumpTarget primitive(this); | 1797 JumpTarget primitive(this); |
1818 JumpTarget jsobject(this); | 1798 JumpTarget jsobject(this); |
1819 JumpTarget fixed_array(this); | 1799 JumpTarget fixed_array(this); |
1820 JumpTarget entry(this, JumpTarget::BIDIRECTIONAL); | 1800 JumpTarget entry(this, JumpTarget::BIDIRECTIONAL); |
1821 JumpTarget end_del_check(this); | 1801 JumpTarget end_del_check(this); |
1822 JumpTarget exit(this); | 1802 JumpTarget exit(this); |
1823 | 1803 |
1824 // Get the object to enumerate over (converted to JSObject). | 1804 // Get the object to enumerate over (converted to JSObject). |
1825 LoadAndSpill(node->enumerable()); | 1805 LoadAndSpill(node->enumerable()); |
1826 | 1806 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 __ mov(r0, Operand(Smi::FromInt(0))); // init index | 1875 __ mov(r0, Operand(Smi::FromInt(0))); // init index |
1896 frame_->EmitPush(r0); | 1876 frame_->EmitPush(r0); |
1897 | 1877 |
1898 // Condition. | 1878 // Condition. |
1899 entry.Bind(); | 1879 entry.Bind(); |
1900 // sp[0] : index | 1880 // sp[0] : index |
1901 // sp[1] : array/enum cache length | 1881 // sp[1] : array/enum cache length |
1902 // sp[2] : array or enum cache | 1882 // sp[2] : array or enum cache |
1903 // sp[3] : 0 or map | 1883 // sp[3] : 0 or map |
1904 // sp[4] : enumerable | 1884 // sp[4] : enumerable |
| 1885 // Grab the current frame's height for the break and continue |
| 1886 // targets only after all the state is pushed on the frame. |
| 1887 node->break_target()->Initialize(this); |
| 1888 node->continue_target()->Initialize(this); |
| 1889 |
1905 __ ldr(r0, frame_->ElementAt(0)); // load the current count | 1890 __ ldr(r0, frame_->ElementAt(0)); // load the current count |
1906 __ ldr(r1, frame_->ElementAt(1)); // load the length | 1891 __ ldr(r1, frame_->ElementAt(1)); // load the length |
1907 __ cmp(r0, Operand(r1)); // compare to the array length | 1892 __ cmp(r0, Operand(r1)); // compare to the array length |
1908 node->break_target()->Branch(hs); | 1893 node->break_target()->Branch(hs); |
1909 | 1894 |
1910 __ ldr(r0, frame_->ElementAt(0)); | 1895 __ ldr(r0, frame_->ElementAt(0)); |
1911 | 1896 |
1912 // Get the i'th entry of the array. | 1897 // Get the i'th entry of the array. |
1913 __ ldr(r2, frame_->ElementAt(2)); | 1898 __ ldr(r2, frame_->ElementAt(2)); |
1914 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1899 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1979 __ add(r0, r0, Operand(Smi::FromInt(1))); | 1964 __ add(r0, r0, Operand(Smi::FromInt(1))); |
1980 frame_->EmitPush(r0); | 1965 frame_->EmitPush(r0); |
1981 entry.Jump(); | 1966 entry.Jump(); |
1982 | 1967 |
1983 // Cleanup. | 1968 // Cleanup. |
1984 node->break_target()->Bind(); | 1969 node->break_target()->Bind(); |
1985 frame_->Drop(5); | 1970 frame_->Drop(5); |
1986 | 1971 |
1987 // Exit. | 1972 // Exit. |
1988 exit.Bind(); | 1973 exit.Bind(); |
1989 break_stack_height_ -= kForInStackSize; | |
1990 ASSERT(frame_->height() == original_height); | 1974 ASSERT(frame_->height() == original_height); |
1991 } | 1975 } |
1992 | 1976 |
1993 | 1977 |
1994 void CodeGenerator::VisitTryCatch(TryCatch* node) { | 1978 void CodeGenerator::VisitTryCatch(TryCatch* node) { |
1995 #ifdef DEBUG | 1979 #ifdef DEBUG |
1996 int original_height = frame_->height(); | 1980 int original_height = frame_->height(); |
1997 #endif | 1981 #endif |
1998 VirtualFrame::SpilledScope spilled_scope(this); | 1982 VirtualFrame::SpilledScope spilled_scope(this); |
1999 Comment cmnt(masm_, "[ TryCatch"); | 1983 Comment cmnt(masm_, "[ TryCatch"); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2252 } | 2236 } |
2253 } | 2237 } |
2254 | 2238 |
2255 // --- Finally block --- | 2239 // --- Finally block --- |
2256 finally_block.Bind(); | 2240 finally_block.Bind(); |
2257 | 2241 |
2258 // Push the state on the stack. | 2242 // Push the state on the stack. |
2259 frame_->EmitPush(r2); | 2243 frame_->EmitPush(r2); |
2260 | 2244 |
2261 // We keep two elements on the stack - the (possibly faked) result | 2245 // We keep two elements on the stack - the (possibly faked) result |
2262 // and the state - while evaluating the finally block. Record it, so | 2246 // and the state - while evaluating the finally block. |
2263 // that a break/continue crossing this statement can restore the | 2247 // |
2264 // stack. | |
2265 const int kFinallyStackSize = 2 * kPointerSize; | |
2266 break_stack_height_ += kFinallyStackSize; | |
2267 | |
2268 // Generate code for the statements in the finally block. | 2248 // Generate code for the statements in the finally block. |
2269 VisitStatementsAndSpill(node->finally_block()->statements()); | 2249 VisitStatementsAndSpill(node->finally_block()->statements()); |
2270 | 2250 |
2271 break_stack_height_ -= kFinallyStackSize; | |
2272 if (has_valid_frame()) { | 2251 if (has_valid_frame()) { |
2273 JumpTarget exit(this); | 2252 JumpTarget exit(this); |
2274 // Restore state and return value or faked TOS. | 2253 // Restore state and return value or faked TOS. |
2275 frame_->EmitPop(r2); | 2254 frame_->EmitPop(r2); |
2276 frame_->EmitPop(r0); | 2255 frame_->EmitPop(r0); |
2277 | 2256 |
2278 // Generate code to jump to the right destination for all used (formerly) | 2257 // Generate code to jump to the right destination for all used (formerly) |
2279 // shadowing labels. | 2258 // shadowing labels. |
2280 for (int i = 0; i <= nof_escapes; i++) { | 2259 for (int i = 0; i <= nof_escapes; i++) { |
2281 if (shadows[i]->is_bound()) { | 2260 if (shadows[i]->is_bound()) { |
(...skipping 2875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5157 __ mov(r2, Operand(0)); | 5136 __ mov(r2, Operand(0)); |
5158 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 5137 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
5159 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 5138 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
5160 RelocInfo::CODE_TARGET); | 5139 RelocInfo::CODE_TARGET); |
5161 } | 5140 } |
5162 | 5141 |
5163 | 5142 |
5164 #undef __ | 5143 #undef __ |
5165 | 5144 |
5166 } } // namespace v8::internal | 5145 } } // namespace v8::internal |
OLD | NEW |