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 |
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 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
| 30 #include "codegen-inl.h" |
30 #include "data-flow.h" | 31 #include "data-flow.h" |
31 #include "fast-codegen.h" | 32 #include "fast-codegen.h" |
| 33 #include "full-codegen.h" |
32 #include "scopes.h" | 34 #include "scopes.h" |
33 | 35 |
34 namespace v8 { | 36 namespace v8 { |
35 namespace internal { | 37 namespace internal { |
36 | 38 |
37 #define BAILOUT(reason) \ | 39 #define BAILOUT(reason) \ |
38 do { \ | 40 do { \ |
39 if (FLAG_trace_bailout) { \ | 41 if (FLAG_trace_bailout) { \ |
40 PrintF("%s\n", reason); \ | 42 PrintF("%s\n", reason); \ |
41 } \ | 43 } \ |
42 has_supported_syntax_ = false; \ | 44 has_supported_syntax_ = false; \ |
43 return; \ | 45 return; \ |
44 } while (false) | 46 } while (false) |
45 | 47 |
46 | 48 |
47 #define CHECK_BAILOUT \ | 49 #define CHECK_BAILOUT \ |
48 do { \ | 50 do { \ |
49 if (!has_supported_syntax_) return; \ | 51 if (!has_supported_syntax_) return; \ |
50 } while (false) | 52 } while (false) |
51 | 53 |
52 | 54 |
53 void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun, | 55 void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun, |
54 CompilationInfo* info) { | 56 CompilationInfo* info) { |
55 info_ = info; | 57 info_ = info; |
56 | 58 |
57 // We do not specialize if we do not have a receiver. | 59 // We do not specialize if we do not have a receiver or if it is not a |
| 60 // JS object with fast mode properties. |
58 if (!info->has_receiver()) BAILOUT("No receiver"); | 61 if (!info->has_receiver()) BAILOUT("No receiver"); |
| 62 if (!info->receiver()->IsJSObject()) BAILOUT("Receiver is not an object"); |
| 63 Handle<JSObject> object = Handle<JSObject>::cast(info->receiver()); |
| 64 if (!object->HasFastProperties()) BAILOUT("Receiver is in dictionary mode"); |
59 | 65 |
60 // We do not support stack or heap slots (both of which require | 66 // We do not support stack or heap slots (both of which require |
61 // allocation). | 67 // allocation). |
62 Scope* scope = fun->scope(); | 68 Scope* scope = fun->scope(); |
63 if (scope->num_stack_slots() > 0) { | 69 if (scope->num_stack_slots() > 0) { |
64 BAILOUT("Function has stack-allocated locals"); | 70 BAILOUT("Function has stack-allocated locals"); |
65 } | 71 } |
66 if (scope->num_heap_slots() > 0) { | 72 if (scope->num_heap_slots() > 0) { |
67 BAILOUT("Function has context-allocated locals"); | 73 BAILOUT("Function has context-allocated locals"); |
68 } | 74 } |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 | 324 |
319 | 325 |
320 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { | 326 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { |
321 BAILOUT("ThisFunction"); | 327 BAILOUT("ThisFunction"); |
322 } | 328 } |
323 | 329 |
324 #undef BAILOUT | 330 #undef BAILOUT |
325 #undef CHECK_BAILOUT | 331 #undef CHECK_BAILOUT |
326 | 332 |
327 | 333 |
328 void FastCodeGenerator::MakeCode(FunctionLiteral* fun, | 334 #define __ ACCESS_MASM(masm()) |
329 Handle<Script> script, | 335 |
330 bool is_eval, | 336 Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun, |
331 CompilationInfo* info) { | 337 Handle<Script> script, |
| 338 bool is_eval, |
| 339 CompilationInfo* info) { |
| 340 // Label the AST before calling MakeCodePrologue, so AST node numbers are |
| 341 // printed with the AST. |
332 AstLabeler labeler; | 342 AstLabeler labeler; |
333 FastCodeGenerator cgen(script, is_eval); | |
334 labeler.Label(fun); | 343 labeler.Label(fun); |
335 cgen.Generate(fun, info); | 344 info->set_has_this_properties(labeler.has_this_properties()); |
| 345 |
| 346 CodeGenerator::MakeCodePrologue(fun); |
| 347 |
| 348 const int kInitialBufferSize = 4 * KB; |
| 349 MacroAssembler masm(NULL, kInitialBufferSize); |
| 350 |
| 351 // Generate the fast-path code. |
| 352 FastCodeGenerator fast_cgen(&masm, script, is_eval); |
| 353 fast_cgen.Generate(fun, info); |
| 354 if (fast_cgen.HasStackOverflow()) { |
| 355 ASSERT(!Top::has_pending_exception()); |
| 356 return Handle<Code>::null(); |
| 357 } |
| 358 |
| 359 // Generate the full code for the function in bailout mode, using the same |
| 360 // macro assembler. |
| 361 FullCodeGenerator full_cgen(&masm, script, is_eval); |
| 362 full_cgen.Generate(fun, FullCodeGenerator::SECONDARY); |
| 363 if (full_cgen.HasStackOverflow()) { |
| 364 ASSERT(!Top::has_pending_exception()); |
| 365 return Handle<Code>::null(); |
| 366 } |
| 367 |
| 368 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); |
| 369 return CodeGenerator::MakeCodeEpilogue(fun, &masm, flags, script); |
336 } | 370 } |
337 | 371 |
338 | 372 |
339 void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) { | |
340 ASSERT(function_ == NULL); | |
341 ASSERT(info_ == NULL); | |
342 function_ = fun; | |
343 info_ = info; | |
344 VisitStatements(fun->body()); | |
345 function_ = NULL; | |
346 info_ = NULL; | |
347 } | |
348 | |
349 | |
350 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { | 373 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { |
351 UNREACHABLE(); | 374 UNREACHABLE(); |
352 } | 375 } |
353 | 376 |
354 | 377 |
355 void FastCodeGenerator::VisitBlock(Block* stmt) { | 378 void FastCodeGenerator::VisitBlock(Block* stmt) { |
356 VisitStatements(stmt->statements()); | 379 VisitStatements(stmt->statements()); |
357 } | 380 } |
358 | 381 |
359 | 382 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 UNREACHABLE(); | 475 UNREACHABLE(); |
453 } | 476 } |
454 | 477 |
455 | 478 |
456 void FastCodeGenerator::VisitSlot(Slot* expr) { | 479 void FastCodeGenerator::VisitSlot(Slot* expr) { |
457 UNREACHABLE(); | 480 UNREACHABLE(); |
458 } | 481 } |
459 | 482 |
460 | 483 |
461 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 484 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 485 ASSERT(expr->var()->is_global() && !expr->var()->is_this()); |
| 486 Comment cmnt(masm(), ";; Global"); |
462 if (FLAG_print_ir) { | 487 if (FLAG_print_ir) { |
463 ASSERT(expr->var()->is_global() && !expr->var()->is_this()); | |
464 SmartPointer<char> name = expr->name()->ToCString(); | 488 SmartPointer<char> name = expr->name()->ToCString(); |
465 PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); | 489 PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); |
466 } | 490 } |
| 491 EmitGlobalVariableLoad(expr->name()); |
467 } | 492 } |
468 | 493 |
469 | 494 |
470 void FastCodeGenerator::VisitLiteral(Literal* expr) { | 495 void FastCodeGenerator::VisitLiteral(Literal* expr) { |
471 UNREACHABLE(); | 496 UNREACHABLE(); |
472 } | 497 } |
473 | 498 |
474 | 499 |
475 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 500 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
476 UNREACHABLE(); | 501 UNREACHABLE(); |
(...skipping 12 matching lines...) Expand all Loading... |
489 | 514 |
490 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 515 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
491 UNREACHABLE(); | 516 UNREACHABLE(); |
492 } | 517 } |
493 | 518 |
494 | 519 |
495 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 520 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
496 // Known to be a simple this property assignment. | 521 // Known to be a simple this property assignment. |
497 Visit(expr->value()); | 522 Visit(expr->value()); |
498 | 523 |
| 524 Property* prop = expr->target()->AsProperty(); |
| 525 ASSERT_NOT_NULL(prop); |
| 526 ASSERT_NOT_NULL(prop->obj()->AsVariableProxy()); |
| 527 ASSERT(prop->obj()->AsVariableProxy()->var()->is_this()); |
| 528 ASSERT(prop->key()->IsPropertyName()); |
| 529 Handle<String> name = |
| 530 Handle<String>::cast(prop->key()->AsLiteral()->handle()); |
| 531 |
| 532 Comment cmnt(masm(), ";; Store(this)"); |
499 if (FLAG_print_ir) { | 533 if (FLAG_print_ir) { |
500 Property* prop = expr->target()->AsProperty(); | 534 SmartPointer<char> name_string = name->ToCString(); |
501 ASSERT_NOT_NULL(prop); | |
502 ASSERT_NOT_NULL(prop->obj()->AsVariableProxy()); | |
503 ASSERT(prop->obj()->AsVariableProxy()->var()->is_this()); | |
504 ASSERT(prop->key()->IsPropertyName()); | |
505 Handle<String> key = | |
506 Handle<String>::cast(prop->key()->AsLiteral()->handle()); | |
507 SmartPointer<char> name = key->ToCString(); | |
508 PrintF("%d: t%d = Store(this, \"%s\", t%d)\n", | 535 PrintF("%d: t%d = Store(this, \"%s\", t%d)\n", |
509 expr->num(), expr->num(), *name, expr->value()->num()); | 536 expr->num(), expr->num(), *name_string, expr->value()->num()); |
510 } | 537 } |
| 538 |
| 539 EmitThisPropertyStore(name); |
511 } | 540 } |
512 | 541 |
513 | 542 |
514 void FastCodeGenerator::VisitThrow(Throw* expr) { | 543 void FastCodeGenerator::VisitThrow(Throw* expr) { |
515 UNREACHABLE(); | 544 UNREACHABLE(); |
516 } | 545 } |
517 | 546 |
518 | 547 |
519 void FastCodeGenerator::VisitProperty(Property* expr) { | 548 void FastCodeGenerator::VisitProperty(Property* expr) { |
520 UNREACHABLE(); | 549 UNREACHABLE(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 | 582 |
554 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 583 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
555 UNREACHABLE(); | 584 UNREACHABLE(); |
556 } | 585 } |
557 | 586 |
558 | 587 |
559 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 588 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
560 UNREACHABLE(); | 589 UNREACHABLE(); |
561 } | 590 } |
562 | 591 |
| 592 #undef __ |
| 593 |
| 594 |
563 } } // namespace v8::internal | 595 } } // namespace v8::internal |
OLD | NEW |