Chromium Code Reviews| 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 |