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

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

Issue 42017: Fix issue 265 by handling extra statement state on the frame based on... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/codegen-arm.h ('k') | src/codegen-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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_ = &register_allocator; 105 allocator_ = &register_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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/codegen-arm.h ('k') | src/codegen-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698