| 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 |