OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 // CodeGenerator implementation | 126 // CodeGenerator implementation |
127 | 127 |
128 CodeGenerator::CodeGenerator(MacroAssembler* masm) | 128 CodeGenerator::CodeGenerator(MacroAssembler* masm) |
129 : deferred_(8), | 129 : deferred_(8), |
130 masm_(masm), | 130 masm_(masm), |
131 info_(NULL), | 131 info_(NULL), |
132 frame_(NULL), | 132 frame_(NULL), |
133 allocator_(NULL), | 133 allocator_(NULL), |
134 cc_reg_(al), | 134 cc_reg_(al), |
135 state_(NULL), | 135 state_(NULL), |
136 loop_nesting_(0), | |
136 function_return_is_shadowed_(false) { | 137 function_return_is_shadowed_(false) { |
137 } | 138 } |
138 | 139 |
139 | 140 |
140 // Calling conventions: | 141 // Calling conventions: |
141 // fp: caller's frame pointer | 142 // fp: caller's frame pointer |
142 // sp: stack pointer | 143 // sp: stack pointer |
143 // r1: called JS function | 144 // r1: called JS function |
144 // cp: callee's context | 145 // cp: callee's context |
145 | 146 |
146 void CodeGenerator::Generate(CompilationInfo* info) { | 147 void CodeGenerator::Generate(CompilationInfo* info) { |
147 // Record the position for debugging purposes. | 148 // Record the position for debugging purposes. |
148 CodeForFunctionPosition(info->function()); | 149 CodeForFunctionPosition(info->function()); |
149 Comment cmnt(masm_, "[ function compiled by virtual frame code generator"); | 150 Comment cmnt(masm_, "[ function compiled by virtual frame code generator"); |
150 | 151 |
151 // Initialize state. | 152 // Initialize state. |
152 info_ = info; | 153 info_ = info; |
153 ASSERT(allocator_ == NULL); | 154 ASSERT(allocator_ == NULL); |
154 RegisterAllocator register_allocator(this); | 155 RegisterAllocator register_allocator(this); |
155 allocator_ = ®ister_allocator; | 156 allocator_ = ®ister_allocator; |
156 ASSERT(frame_ == NULL); | 157 ASSERT(frame_ == NULL); |
157 frame_ = new VirtualFrame(); | 158 frame_ = new VirtualFrame(); |
158 cc_reg_ = al; | 159 cc_reg_ = al; |
160 | |
161 // Adjust for function-level loop nesting. | |
162 loop_nesting_ += info->loop_nesting(); | |
163 | |
159 { | 164 { |
160 CodeGenState state(this); | 165 CodeGenState state(this); |
161 | 166 |
162 // Entry: | 167 // Entry: |
163 // Stack: receiver, arguments | 168 // Stack: receiver, arguments |
164 // lr: return address | 169 // lr: return address |
165 // fp: caller's frame pointer | 170 // fp: caller's frame pointer |
166 // sp: stack pointer | 171 // sp: stack pointer |
167 // r1: called JS function | 172 // r1: called JS function |
168 // cp: callee's context | 173 // cp: callee's context |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 // Check that the size of the code used for returning matches what is | 378 // Check that the size of the code used for returning matches what is |
374 // expected by the debugger. The add instruction above is an addressing | 379 // expected by the debugger. The add instruction above is an addressing |
375 // mode 1 instruction where there are restrictions on which immediate values | 380 // mode 1 instruction where there are restrictions on which immediate values |
376 // can be encoded in the instruction and which immediate values requires | 381 // can be encoded in the instruction and which immediate values requires |
377 // use of an additional instruction for moving the immediate to a temporary | 382 // use of an additional instruction for moving the immediate to a temporary |
378 // register. | 383 // register. |
379 ASSERT_EQ(return_sequence_length, | 384 ASSERT_EQ(return_sequence_length, |
380 masm_->InstructionsGeneratedSince(&check_exit_codesize)); | 385 masm_->InstructionsGeneratedSince(&check_exit_codesize)); |
381 } | 386 } |
382 | 387 |
388 // Adjust for function-level loop nesting. | |
389 loop_nesting_ -= info->loop_nesting(); | |
Erik Corry
2010/04/15 12:46:18
Seems simpler to ASSERT that loop_nesting() == inf
| |
390 | |
383 // Code generation state must be reset. | 391 // Code generation state must be reset. |
384 ASSERT(!has_cc()); | 392 ASSERT(!has_cc()); |
385 ASSERT(state_ == NULL); | 393 ASSERT(state_ == NULL); |
394 ASSERT(loop_nesting() == 0); | |
386 ASSERT(!function_return_is_shadowed_); | 395 ASSERT(!function_return_is_shadowed_); |
387 function_return_.Unuse(); | 396 function_return_.Unuse(); |
388 DeleteFrame(); | 397 DeleteFrame(); |
389 | 398 |
390 // Process any deferred code using the register allocator. | 399 // Process any deferred code using the register allocator. |
391 if (!HasStackOverflow()) { | 400 if (!HasStackOverflow()) { |
392 ProcessDeferred(); | 401 ProcessDeferred(); |
393 } | 402 } |
394 | 403 |
395 allocator_ = NULL; | 404 allocator_ = NULL; |
(...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1878 | 1887 |
1879 void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) { | 1888 void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) { |
1880 #ifdef DEBUG | 1889 #ifdef DEBUG |
1881 int original_height = frame_->height(); | 1890 int original_height = frame_->height(); |
1882 #endif | 1891 #endif |
1883 VirtualFrame::SpilledScope spilled_scope(frame_); | 1892 VirtualFrame::SpilledScope spilled_scope(frame_); |
1884 Comment cmnt(masm_, "[ DoWhileStatement"); | 1893 Comment cmnt(masm_, "[ DoWhileStatement"); |
1885 CodeForStatementPosition(node); | 1894 CodeForStatementPosition(node); |
1886 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | 1895 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
1887 JumpTarget body(JumpTarget::BIDIRECTIONAL); | 1896 JumpTarget body(JumpTarget::BIDIRECTIONAL); |
1897 IncrementLoopNesting(); | |
1888 | 1898 |
1889 // Label the top of the loop for the backward CFG edge. If the test | 1899 // Label the top of the loop for the backward CFG edge. If the test |
1890 // is always true we can use the continue target, and if the test is | 1900 // is always true we can use the continue target, and if the test is |
1891 // always false there is no need. | 1901 // always false there is no need. |
1892 ConditionAnalysis info = AnalyzeCondition(node->cond()); | 1902 ConditionAnalysis info = AnalyzeCondition(node->cond()); |
1893 switch (info) { | 1903 switch (info) { |
1894 case ALWAYS_TRUE: | 1904 case ALWAYS_TRUE: |
1895 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); | 1905 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); |
1896 node->continue_target()->Bind(); | 1906 node->continue_target()->Bind(); |
1897 break; | 1907 break; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1938 // fall out of the test expression. | 1948 // fall out of the test expression. |
1939 Branch(true, &body); | 1949 Branch(true, &body); |
1940 } | 1950 } |
1941 } | 1951 } |
1942 break; | 1952 break; |
1943 } | 1953 } |
1944 | 1954 |
1945 if (node->break_target()->is_linked()) { | 1955 if (node->break_target()->is_linked()) { |
1946 node->break_target()->Bind(); | 1956 node->break_target()->Bind(); |
1947 } | 1957 } |
1958 DecrementLoopNesting(); | |
1948 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1959 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
1949 } | 1960 } |
1950 | 1961 |
1951 | 1962 |
1952 void CodeGenerator::VisitWhileStatement(WhileStatement* node) { | 1963 void CodeGenerator::VisitWhileStatement(WhileStatement* node) { |
1953 #ifdef DEBUG | 1964 #ifdef DEBUG |
1954 int original_height = frame_->height(); | 1965 int original_height = frame_->height(); |
1955 #endif | 1966 #endif |
1956 VirtualFrame::SpilledScope spilled_scope(frame_); | 1967 VirtualFrame::SpilledScope spilled_scope(frame_); |
1957 Comment cmnt(masm_, "[ WhileStatement"); | 1968 Comment cmnt(masm_, "[ WhileStatement"); |
1958 CodeForStatementPosition(node); | 1969 CodeForStatementPosition(node); |
1959 | 1970 |
1960 // If the test is never true and has no side effects there is no need | 1971 // If the test is never true and has no side effects there is no need |
1961 // to compile the test or body. | 1972 // to compile the test or body. |
1962 ConditionAnalysis info = AnalyzeCondition(node->cond()); | 1973 ConditionAnalysis info = AnalyzeCondition(node->cond()); |
1963 if (info == ALWAYS_FALSE) return; | 1974 if (info == ALWAYS_FALSE) return; |
1964 | 1975 |
1965 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | 1976 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
1977 IncrementLoopNesting(); | |
1966 | 1978 |
1967 // Label the top of the loop with the continue target for the backward | 1979 // Label the top of the loop with the continue target for the backward |
1968 // CFG edge. | 1980 // CFG edge. |
1969 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); | 1981 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); |
1970 node->continue_target()->Bind(); | 1982 node->continue_target()->Bind(); |
1971 | 1983 |
1972 if (info == DONT_KNOW) { | 1984 if (info == DONT_KNOW) { |
1973 JumpTarget body; | 1985 JumpTarget body; |
1974 LoadConditionAndSpill(node->cond(), &body, node->break_target(), true); | 1986 LoadConditionAndSpill(node->cond(), &body, node->break_target(), true); |
1975 if (has_valid_frame()) { | 1987 if (has_valid_frame()) { |
(...skipping 11 matching lines...) Expand all Loading... | |
1987 VisitAndSpill(node->body()); | 1999 VisitAndSpill(node->body()); |
1988 | 2000 |
1989 // If control flow can fall out of the body, jump back to the top. | 2001 // If control flow can fall out of the body, jump back to the top. |
1990 if (has_valid_frame()) { | 2002 if (has_valid_frame()) { |
1991 node->continue_target()->Jump(); | 2003 node->continue_target()->Jump(); |
1992 } | 2004 } |
1993 } | 2005 } |
1994 if (node->break_target()->is_linked()) { | 2006 if (node->break_target()->is_linked()) { |
1995 node->break_target()->Bind(); | 2007 node->break_target()->Bind(); |
1996 } | 2008 } |
2009 DecrementLoopNesting(); | |
1997 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 2010 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
1998 } | 2011 } |
1999 | 2012 |
2000 | 2013 |
2001 void CodeGenerator::VisitForStatement(ForStatement* node) { | 2014 void CodeGenerator::VisitForStatement(ForStatement* node) { |
2002 #ifdef DEBUG | 2015 #ifdef DEBUG |
2003 int original_height = frame_->height(); | 2016 int original_height = frame_->height(); |
2004 #endif | 2017 #endif |
2005 VirtualFrame::SpilledScope spilled_scope(frame_); | 2018 VirtualFrame::SpilledScope spilled_scope(frame_); |
2006 Comment cmnt(masm_, "[ ForStatement"); | 2019 Comment cmnt(masm_, "[ ForStatement"); |
2007 CodeForStatementPosition(node); | 2020 CodeForStatementPosition(node); |
2008 if (node->init() != NULL) { | 2021 if (node->init() != NULL) { |
2009 VisitAndSpill(node->init()); | 2022 VisitAndSpill(node->init()); |
2010 } | 2023 } |
2011 | 2024 |
2012 // If the test is never true there is no need to compile the test or | 2025 // If the test is never true there is no need to compile the test or |
2013 // body. | 2026 // body. |
2014 ConditionAnalysis info = AnalyzeCondition(node->cond()); | 2027 ConditionAnalysis info = AnalyzeCondition(node->cond()); |
2015 if (info == ALWAYS_FALSE) return; | 2028 if (info == ALWAYS_FALSE) return; |
2016 | 2029 |
2017 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | 2030 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
2031 IncrementLoopNesting(); | |
2018 | 2032 |
2019 // If there is no update statement, label the top of the loop with the | 2033 // If there is no update statement, label the top of the loop with the |
2020 // continue target, otherwise with the loop target. | 2034 // continue target, otherwise with the loop target. |
2021 JumpTarget loop(JumpTarget::BIDIRECTIONAL); | 2035 JumpTarget loop(JumpTarget::BIDIRECTIONAL); |
2022 if (node->next() == NULL) { | 2036 if (node->next() == NULL) { |
2023 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); | 2037 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); |
2024 node->continue_target()->Bind(); | 2038 node->continue_target()->Bind(); |
2025 } else { | 2039 } else { |
2026 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); | 2040 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); |
2027 loop.Bind(); | 2041 loop.Bind(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2062 // statement and not the body. | 2076 // statement and not the body. |
2063 CodeForStatementPosition(node); | 2077 CodeForStatementPosition(node); |
2064 VisitAndSpill(node->next()); | 2078 VisitAndSpill(node->next()); |
2065 loop.Jump(); | 2079 loop.Jump(); |
2066 } | 2080 } |
2067 } | 2081 } |
2068 } | 2082 } |
2069 if (node->break_target()->is_linked()) { | 2083 if (node->break_target()->is_linked()) { |
2070 node->break_target()->Bind(); | 2084 node->break_target()->Bind(); |
2071 } | 2085 } |
2086 DecrementLoopNesting(); | |
2072 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 2087 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
2073 } | 2088 } |
2074 | 2089 |
2075 | 2090 |
2076 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 2091 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
Erik Corry
2010/04/15 12:46:18
Wot no loop nesting?
| |
2077 #ifdef DEBUG | 2092 #ifdef DEBUG |
2078 int original_height = frame_->height(); | 2093 int original_height = frame_->height(); |
2079 #endif | 2094 #endif |
2080 VirtualFrame::SpilledScope spilled_scope(frame_); | 2095 VirtualFrame::SpilledScope spilled_scope(frame_); |
2081 Comment cmnt(masm_, "[ ForInStatement"); | 2096 Comment cmnt(masm_, "[ ForInStatement"); |
2082 CodeForStatementPosition(node); | 2097 CodeForStatementPosition(node); |
2083 | 2098 |
2084 JumpTarget primitive; | 2099 JumpTarget primitive; |
2085 JumpTarget jsobject; | 2100 JumpTarget jsobject; |
2086 JumpTarget fixed_array; | 2101 JumpTarget fixed_array; |
(...skipping 6852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8939 | 8954 |
8940 // Just jump to runtime to add the two strings. | 8955 // Just jump to runtime to add the two strings. |
8941 __ bind(&string_add_runtime); | 8956 __ bind(&string_add_runtime); |
8942 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 8957 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
8943 } | 8958 } |
8944 | 8959 |
8945 | 8960 |
8946 #undef __ | 8961 #undef __ |
8947 | 8962 |
8948 } } // namespace v8::internal | 8963 } } // namespace v8::internal |
OLD | NEW |