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 |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 | 28 |
29 #include "v8.h" | 29 #include "v8.h" |
30 #include "macro-assembler.h" | 30 |
| 31 #include "bootstrapper.h" |
| 32 // #include "macro-assembler.h" |
| 33 #include "codegen-inl.h" |
31 #include "register-allocator-inl.h" | 34 #include "register-allocator-inl.h" |
32 #include "codegen-inl.h" | |
33 #include "codegen-x64-inl.h" | |
34 | 35 |
35 // TEST | 36 // TEST |
36 #include "compiler.h" | 37 #include "compiler.h" |
37 | 38 |
38 namespace v8 { | 39 namespace v8 { |
39 namespace internal { | 40 namespace internal { |
40 | 41 |
41 // ------------------------------------------------------------------------- | 42 // ------------------------------------------------------------------------- |
42 // Platform-specific DeferredCode functions. | 43 // Platform-specific DeferredCode functions. |
43 | 44 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 | 99 |
99 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { | 100 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { |
100 UNIMPLEMENTED(); | 101 UNIMPLEMENTED(); |
101 } | 102 } |
102 | 103 |
103 void CodeGenerator::TestCodeGenerator() { | 104 void CodeGenerator::TestCodeGenerator() { |
104 // Compile a function from a string, and run it. | 105 // Compile a function from a string, and run it. |
105 Handle<JSFunction> test_function = Compiler::Compile( | 106 Handle<JSFunction> test_function = Compiler::Compile( |
106 Factory::NewStringFromAscii(CStrVector( | 107 Factory::NewStringFromAscii(CStrVector( |
107 "39;" | 108 "39;" |
108 "(function(){return 43})();" | 109 "(function(){" |
109 "42;" | 110 "function foo(x, y){var w; y = x; x = w; w = y; y = x; return w;};" |
110 // "function foo(x, y){return x;};" | 111 "function bar(x, y, zee){return zee;};" |
111 "43;" | 112 "foo(2,3);" |
112 // "foo(2,3);" | 113 "return foo(bar(foo(1,3), 42, 47), foo( -25.3, 2));" |
113 "44;" | 114 "})()")), |
114 "(function(){return (function(){return 47})()})();")), | |
115 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), | 115 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), |
116 0, | 116 0, |
117 0, | 117 0, |
118 NULL, | 118 NULL, |
119 NULL); | 119 NULL); |
120 | 120 |
121 Code* code_object = test_function->code(); // Local for debugging ease. | 121 Code* code_object = test_function->code(); // Local for debugging ease. |
122 USE(code_object); | 122 USE(code_object); |
123 | 123 |
124 // Create a dummy function and context. | 124 // Create a dummy function and context. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 allocator_->Initialize(); | 187 allocator_->Initialize(); |
188 frame_->Enter(); | 188 frame_->Enter(); |
189 | 189 |
190 // Allocate space for locals and initialize them. | 190 // Allocate space for locals and initialize them. |
191 frame_->AllocateStackSlots(); | 191 frame_->AllocateStackSlots(); |
192 // Initialize the function return target after the locals are set | 192 // Initialize the function return target after the locals are set |
193 // up, because it needs the expected frame height from the frame. | 193 // up, because it needs the expected frame height from the frame. |
194 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | 194 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
195 function_return_is_shadowed_ = false; | 195 function_return_is_shadowed_ = false; |
196 | 196 |
| 197 // TODO(X64): Add code to handle arguments object and context object. |
| 198 |
| 199 // Generate code to 'execute' declarations and initialize functions |
| 200 // (source elements). In case of an illegal redeclaration we need to |
| 201 // handle that instead of processing the declarations. |
| 202 if (scope_->HasIllegalRedeclaration()) { |
| 203 Comment cmnt(masm_, "[ illegal redeclarations"); |
| 204 scope_->VisitIllegalRedeclaration(this); |
| 205 } else { |
| 206 Comment cmnt(masm_, "[ declarations"); |
| 207 ProcessDeclarations(scope_->declarations()); |
| 208 // Bail out if a stack-overflow exception occurred when processing |
| 209 // declarations. |
| 210 if (HasStackOverflow()) return; |
| 211 } |
| 212 |
| 213 if (FLAG_trace) { |
| 214 frame_->CallRuntime(Runtime::kTraceEnter, 0); |
| 215 // Ignore the return value. |
| 216 } |
| 217 // CheckStack(); |
| 218 |
| 219 // Compile the body of the function in a vanilla state. Don't |
| 220 // bother compiling all the code if the scope has an illegal |
| 221 // redeclaration. |
| 222 if (!scope_->HasIllegalRedeclaration()) { |
| 223 Comment cmnt(masm_, "[ function body"); |
| 224 #ifdef DEBUG |
| 225 bool is_builtin = Bootstrapper::IsActive(); |
| 226 bool should_trace = |
| 227 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
| 228 if (should_trace) { |
| 229 frame_->CallRuntime(Runtime::kDebugTrace, 0); |
| 230 // Ignore the return value. |
| 231 } |
| 232 #endif |
| 233 } |
| 234 |
197 VisitStatements(body); | 235 VisitStatements(body); |
198 } | 236 } |
199 // Adjust for function-level loop nesting. | 237 // Adjust for function-level loop nesting. |
200 loop_nesting_ -= function->loop_nesting(); | 238 loop_nesting_ -= function->loop_nesting(); |
201 | 239 |
202 // Code generation state must be reset. | 240 // Code generation state must be reset. |
203 ASSERT(state_ == NULL); | 241 ASSERT(state_ == NULL); |
204 ASSERT(loop_nesting() == 0); | 242 ASSERT(loop_nesting() == 0); |
205 ASSERT(!function_return_is_shadowed_); | 243 ASSERT(!function_return_is_shadowed_); |
206 function_return_.Unuse(); | 244 function_return_.Unuse(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 | 314 |
277 | 315 |
278 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 316 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
279 ASSERT(!in_spilled_code()); | 317 ASSERT(!in_spilled_code()); |
280 for (int i = 0; has_valid_frame() && i < statements->length(); i++) { | 318 for (int i = 0; has_valid_frame() && i < statements->length(); i++) { |
281 Visit(statements->at(i)); | 319 Visit(statements->at(i)); |
282 } | 320 } |
283 } | 321 } |
284 | 322 |
285 | 323 |
286 void CodeGenerator::VisitBlock(Block* a) { | 324 void CodeGenerator::VisitBlock(Block* node) { |
287 UNIMPLEMENTED(); | 325 ASSERT(!in_spilled_code()); |
288 } | 326 Comment cmnt(masm_, "[ Block"); |
289 | 327 CodeForStatementPosition(node); |
290 void CodeGenerator::VisitDeclaration(Declaration* a) { | 328 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
291 UNIMPLEMENTED(); | 329 VisitStatements(node->statements()); |
| 330 if (node->break_target()->is_linked()) { |
| 331 node->break_target()->Bind(); |
| 332 } |
| 333 node->break_target()->Unuse(); |
292 } | 334 } |
293 | 335 |
294 | 336 |
| 337 void CodeGenerator::VisitDeclaration(Declaration* node) { |
| 338 Comment cmnt(masm_, "[ Declaration"); |
| 339 CodeForStatementPosition(node); |
| 340 Variable* var = node->proxy()->var(); |
| 341 ASSERT(var != NULL); // must have been resolved |
| 342 Slot* slot = var->slot(); |
| 343 |
| 344 // If it was not possible to allocate the variable at compile time, |
| 345 // we need to "declare" it at runtime to make sure it actually |
| 346 // exists in the local context. |
| 347 if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 348 // Variables with a "LOOKUP" slot were introduced as non-locals |
| 349 // during variable resolution and must have mode DYNAMIC. |
| 350 ASSERT(var->is_dynamic()); |
| 351 // For now, just do a runtime call. Sync the virtual frame eagerly |
| 352 // so we can simply push the arguments into place. |
| 353 frame_->SyncRange(0, frame_->element_count() - 1); |
| 354 frame_->EmitPush(rsi); |
| 355 __ movq(kScratchRegister, var->name(), RelocInfo::EMBEDDED_OBJECT); |
| 356 frame_->EmitPush(kScratchRegister); |
| 357 // Declaration nodes are always introduced in one of two modes. |
| 358 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); |
| 359 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; |
| 360 frame_->EmitPush(Immediate(Smi::FromInt(attr))); |
| 361 // Push initial value, if any. |
| 362 // Note: For variables we must not push an initial value (such as |
| 363 // 'undefined') because we may have a (legal) redeclaration and we |
| 364 // must not destroy the current value. |
| 365 if (node->mode() == Variable::CONST) { |
| 366 __ movq(kScratchRegister, Factory::the_hole_value(), |
| 367 RelocInfo::EMBEDDED_OBJECT); |
| 368 frame_->EmitPush(kScratchRegister); |
| 369 } else if (node->fun() != NULL) { |
| 370 Load(node->fun()); |
| 371 } else { |
| 372 frame_->EmitPush(Immediate(Smi::FromInt(0))); // no initial value! |
| 373 } |
| 374 Result ignored = frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 375 // Ignore the return value (declarations are statements). |
| 376 return; |
| 377 } |
| 378 |
| 379 ASSERT(!var->is_global()); |
| 380 |
| 381 // If we have a function or a constant, we need to initialize the variable. |
| 382 Expression* val = NULL; |
| 383 if (node->mode() == Variable::CONST) { |
| 384 val = new Literal(Factory::the_hole_value()); |
| 385 } else { |
| 386 val = node->fun(); // NULL if we don't have a function |
| 387 } |
| 388 |
| 389 if (val != NULL) { |
| 390 { |
| 391 // Set the initial value. |
| 392 Reference target(this, node->proxy()); |
| 393 Load(val); |
| 394 target.SetValue(NOT_CONST_INIT); |
| 395 // The reference is removed from the stack (preserving TOS) when |
| 396 // it goes out of scope. |
| 397 } |
| 398 // Get rid of the assigned value (declarations are statements). |
| 399 frame_->Drop(); |
| 400 } |
| 401 } |
| 402 |
| 403 |
295 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 404 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
296 ASSERT(!in_spilled_code()); | 405 ASSERT(!in_spilled_code()); |
297 Comment cmnt(masm_, "[ ExpressionStatement"); | 406 Comment cmnt(masm_, "[ ExpressionStatement"); |
298 CodeForStatementPosition(node); | 407 CodeForStatementPosition(node); |
299 Expression* expression = node->expression(); | 408 Expression* expression = node->expression(); |
300 expression->MarkAsStatement(); | 409 expression->MarkAsStatement(); |
301 Load(expression); | 410 Load(expression); |
302 // Remove the lingering expression result from the top of stack. | 411 // Remove the lingering expression result from the top of stack. |
303 frame_->Drop(); | 412 frame_->Drop(); |
304 } | 413 } |
(...skipping 1977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2282 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers | 2391 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers |
2283 | 2392 |
2284 // Restore frame pointer and return. | 2393 // Restore frame pointer and return. |
2285 __ pop(rbp); | 2394 __ pop(rbp); |
2286 __ ret(0); | 2395 __ ret(0); |
2287 } | 2396 } |
2288 | 2397 |
2289 #undef __ | 2398 #undef __ |
2290 | 2399 |
2291 } } // namespace v8::internal | 2400 } } // namespace v8::internal |
OLD | NEW |