1 // Copyright 2010 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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. 27 28 #include "v8.h" 29 30 #include "codegen-inl.h" 31 #include "data-flow.h" 32 #include "fast-codegen.h" 33 #include "scopes.h" 34 35 namespace v8 { 36 namespace internal { 37 38 #define BAILOUT(reason) \ 39 do { \ 40 if (FLAG_trace_bailout) { \ 41 PrintF("%s\n", reason); \ 42 } \ 43 has_supported_syntax_ = false; \ 44 return; \ 45 } while (false) 46 47 48 #define CHECK_BAILOUT \ 49 do { \ 50 if (!has_supported_syntax_) return; \ 51 } while (false) 52 53 54 void FastCodeGenSyntaxChecker::Check(CompilationInfo* info) { 55 info_ = info; 56 57 // We do not specialize if we do not have a receiver or if it is not a 58 // JS object with fast mode properties. 59 if (!info->has_receiver()) BAILOUT("No receiver"); 60 if (!info->receiver()->IsJSObject()) BAILOUT("Receiver is not an object"); 61 Handle<JSObject> object = Handle<JSObject>::cast(info->receiver()); 62 if (!object->HasFastProperties()) BAILOUT("Receiver is in dictionary mode"); 63 64 // We do not support stack or heap slots (both of which require 65 // allocation). 66 Scope* scope = info->scope(); 67 if (scope->num_stack_slots() > 0) { 68 BAILOUT("Function has stack-allocated locals"); 69 } 70 if (scope->num_heap_slots() > 0) { 71 BAILOUT("Function has context-allocated locals"); 72 } 73 74 VisitDeclarations(scope->declarations()); 75 CHECK_BAILOUT; 76 77 // We do not support empty function bodies. 78 if (info->function()->body()->is_empty()) { 79 BAILOUT("Function has an empty body"); 80 } 81 VisitStatements(info->function()->body()); 82 } 83 84 85 void FastCodeGenSyntaxChecker::VisitDeclarations( 86 ZoneList<Declaration*>* decls) { 87 if (!decls->is_empty()) BAILOUT("Function has declarations"); 88 } 89 90 91 void FastCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) { 92 if (stmts->length() != 1) { 93 BAILOUT("Function body is not a singleton statement."); 94 } 95 Visit(stmts->at(0)); 96 } 97 98 99 void FastCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) { 100 UNREACHABLE(); 101 } 102 103 104 void FastCodeGenSyntaxChecker::VisitBlock(Block* stmt) { 105 VisitStatements(stmt->statements()); 106 } 107 108 109 void FastCodeGenSyntaxChecker::VisitExpressionStatement( 110 ExpressionStatement* stmt) { 111 Visit(stmt->expression()); 112 } 113 114 115 void FastCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) { 116 // Supported. 117 } 118 119 120 void FastCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) { 121 BAILOUT("IfStatement"); 122 } 123 124 125 void FastCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) { 126 BAILOUT("Continuestatement"); 127 } 128 129 130 void FastCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) { 131 BAILOUT("BreakStatement"); 132 } 133 134 135 void FastCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) { 136 BAILOUT("ReturnStatement"); 137 } 138 139 140 void FastCodeGenSyntaxChecker::VisitWithEnterStatement( 141 WithEnterStatement* stmt) { 142 BAILOUT("WithEnterStatement"); 143 } 144 145 146 void FastCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) { 147 BAILOUT("WithExitStatement"); 148 } 149 150 151 void FastCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) { 152 BAILOUT("SwitchStatement"); 153 } 154 155 156 void FastCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) { 157 BAILOUT("DoWhileStatement"); 158 } 159 160 161 void FastCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) { 162 BAILOUT("WhileStatement"); 163 } 164 165 166 void FastCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) { 167 BAILOUT("ForStatement"); 168 } 169 170 171 void FastCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) { 172 BAILOUT("ForInStatement"); 173 } 174 175 176 void FastCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) { 177 BAILOUT("TryCatchStatement"); 178 } 179 180 181 void FastCodeGenSyntaxChecker::VisitTryFinallyStatement( 182 TryFinallyStatement* stmt) { 183 BAILOUT("TryFinallyStatement"); 184 } 185 186 187 void FastCodeGenSyntaxChecker::VisitDebuggerStatement( 188 DebuggerStatement* stmt) { 189 BAILOUT("DebuggerStatement"); 190 } 191 192 193 void FastCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) { 194 BAILOUT("FunctionLiteral"); 195 } 196 197 198 void FastCodeGenSyntaxChecker::VisitFunctionBoilerplateLiteral( 199 FunctionBoilerplateLiteral* expr) { 200 BAILOUT("FunctionBoilerplateLiteral"); 201 } 202 203 204 void FastCodeGenSyntaxChecker::VisitConditional(Conditional* expr) { 205 BAILOUT("Conditional"); 206 } 207 208 209 void FastCodeGenSyntaxChecker::VisitSlot(Slot* expr) { 210 UNREACHABLE(); 211 } 212 213 214 void FastCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) { 215 // Only global variable references are supported. 216 Variable* var = expr->var(); 217 if (!var->is_global() || var->is_this()) BAILOUT("Non-global variable"); 218 219 // Check if the global variable is existing and non-deletable. 220 if (info()->has_global_object()) { 221 LookupResult lookup; 222 info()->global_object()->Lookup(*expr->name(), &lookup); 223 if (!lookup.IsProperty()) { 224 BAILOUT("Non-existing global variable"); 225 } 226 // We do not handle global variables with accessors or interceptors. 227 if (lookup.type() != NORMAL) { 228 BAILOUT("Global variable with accessors or interceptors."); 229 } 230 // We do not handle deletable global variables. 231 if (!lookup.IsDontDelete()) { 232 BAILOUT("Deletable global variable"); 233 } 234 } 235 } 236 237 238 void FastCodeGenSyntaxChecker::VisitLiteral(Literal* expr) { 239 BAILOUT("Literal"); 240 } 241 242 243 void FastCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) { 244 BAILOUT("RegExpLiteral"); 245 } 246 247 248 void FastCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) { 249 BAILOUT("ObjectLiteral"); 250 } 251 252 253 void FastCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) { 254 BAILOUT("ArrayLiteral"); 255 } 256 257 258 void FastCodeGenSyntaxChecker::VisitCatchExtensionObject( 259 CatchExtensionObject* expr) { 260 BAILOUT("CatchExtensionObject"); 261 } 262 263 264 void FastCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) { 265 // Simple assignments to (named) this properties are supported. 266 if (expr->op() != Token::ASSIGN) BAILOUT("Non-simple assignment"); 267 268 Property* prop = expr->target()->AsProperty(); 269 if (prop == NULL) BAILOUT("Non-property assignment"); 270 VariableProxy* proxy = prop->obj()->AsVariableProxy(); 271 if (proxy == NULL || !proxy->var()->is_this()) { 272 BAILOUT("Non-this-property assignment"); 273 } 274 if (!prop->key()->IsPropertyName()) { 275 BAILOUT("Non-named-property assignment"); 276 } 277 278 // We will only specialize for fields on the object itself. 279 // Expression::IsPropertyName implies that the name is a literal 280 // symbol but we do not assume that. 281 Literal* key = prop->key()->AsLiteral(); 282 if (key != NULL && key->handle()->IsString()) { 283 Handle<Object> receiver = info()->receiver(); 284 Handle<String> name = Handle<String>::cast(key->handle()); 285 LookupResult lookup; 286 receiver->Lookup(*name, &lookup); 287 if (!lookup.IsProperty()) { 288 BAILOUT("Assigned property not found at compile time"); 289 } 290 if (lookup.holder() != *receiver) BAILOUT("Non-own property assignment"); 291 if (!lookup.type() == FIELD) BAILOUT("Non-field property assignment"); 292 } else { 293 UNREACHABLE(); 294 BAILOUT("Unexpected non-string-literal property key"); 295 } 296 297 Visit(expr->value()); 298 } 299 300 301 void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) { 302 BAILOUT("Throw"); 303 } 304 305 306 void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) { 307 // We support named this property references. 308 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 309 if (proxy == NULL || !proxy->var()->is_this()) { 310 BAILOUT("Non-this-property reference"); 311 } 312 if (!expr->key()->IsPropertyName()) { 313 BAILOUT("Non-named-property reference"); 314 } 315 316 // We will only specialize for fields on the object itself. 317 // Expression::IsPropertyName implies that the name is a literal 318 // symbol but we do not assume that. 319 Literal* key = expr->key()->AsLiteral(); 320 if (key != NULL && key->handle()->IsString()) { 321 Handle<Object> receiver = info()->receiver(); 322 Handle<String> name = Handle<String>::cast(key->handle()); 323 LookupResult lookup; 324 receiver->Lookup(*name, &lookup); 325 if (!lookup.IsProperty()) { 326 BAILOUT("Referenced property not found at compile time"); 327 } 328 if (lookup.holder() != *receiver) BAILOUT("Non-own property reference"); 329 if (!lookup.type() == FIELD) BAILOUT("Non-field property reference"); 330 } else { 331 UNREACHABLE(); 332 BAILOUT("Unexpected non-string-literal property key"); 333 } 334 } 335 336 337 void FastCodeGenSyntaxChecker::VisitCall(Call* expr) { 338 BAILOUT("Call"); 339 } 340 341 342 void FastCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { 343 BAILOUT("CallNew"); 344 } 345 346 347 void FastCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { 348 BAILOUT("CallRuntime"); 349 } 350 351 352 void FastCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { 353 BAILOUT("UnaryOperation"); 354 } 355 356 357 void FastCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { 358 BAILOUT("CountOperation"); 359 } 360 361 362 void FastCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { 363 // We support bitwise OR. 364 switch (expr->op()) { 365 case Token::COMMA: 366 BAILOUT("BinaryOperation COMMA"); 367 case Token::OR: 368 BAILOUT("BinaryOperation OR"); 369 case Token::AND: 370 BAILOUT("BinaryOperation AND"); 371 372 case Token::BIT_OR: 373 // We support expressions nested on the left because they only require 374 // a pair of registers to keep all intermediate values in registers 375 // (i.e., the expression stack has height no more than two). 376 if (!expr->right()->IsLeaf()) BAILOUT("expression nested on right"); 377 378 // We do not allow subexpressions with side effects because we 379 // (currently) bail out to the beginning of the full function. The 380 // only expressions with side effects that we would otherwise handle 381 // are assignments. 382 if (expr->left()->AsAssignment() != NULL || 383 expr->right()->AsAssignment() != NULL) { 384 BAILOUT("subexpression of binary operation has side effects"); 385 } 386 387 Visit(expr->left()); 388 CHECK_BAILOUT; 389 Visit(expr->right()); 390 break; 391 392 case Token::BIT_XOR: 393 BAILOUT("BinaryOperation BIT_XOR"); 394 case Token::BIT_AND: 395 BAILOUT("BinaryOperation BIT_AND"); 396 case Token::SHL: 397 BAILOUT("BinaryOperation SHL"); 398 case Token::SAR: 399 BAILOUT("BinaryOperation SAR"); 400 case Token::SHR: 401 BAILOUT("BinaryOperation SHR"); 402 case Token::ADD: 403 BAILOUT("BinaryOperation ADD"); 404 case Token::SUB: 405 BAILOUT("BinaryOperation SUB"); 406 case Token::MUL: 407 BAILOUT("BinaryOperation MUL"); 408 case Token::DIV: 409 BAILOUT("BinaryOperation DIV"); 410 case Token::MOD: 411 BAILOUT("BinaryOperation MOD"); 412 default: 413 UNREACHABLE(); 414 } 415 } 416 417 418 void FastCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { 419 BAILOUT("CompareOperation"); 420 } 421 422 423 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { 424 BAILOUT("ThisFunction"); 425 } 426 427 #undef BAILOUT 428 #undef CHECK_BAILOUT 429 430 431 #define __ ACCESS_MASM(masm()) 432 433 Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) { 434 // Label the AST before calling MakeCodePrologue, so AST node numbers are 435 // printed with the AST. 436 AstLabeler labeler; 437 labeler.Label(info); 438 439 LivenessAnalyzer analyzer; 440 analyzer.Analyze(info->function()); 441 442 CodeGenerator::MakeCodePrologue(info); 443 444 const int kInitialBufferSize = 4 * KB; 445 MacroAssembler masm(NULL, kInitialBufferSize); 446 447 // Generate the fast-path code. 448 FastCodeGenerator fast_cgen(&masm); 449 fast_cgen.Generate(info); 450 if (fast_cgen.HasStackOverflow()) { 451 ASSERT(!Top::has_pending_exception()); 452 return Handle<Code>::null(); 453 } 454 455 // Generate the full code for the function in bailout mode, using the same 456 // macro assembler. 457 CodeGenerator cgen(&masm); 458 CodeGeneratorScope scope(&cgen); 459 info->set_mode(CompilationInfo::SECONDARY); 460 cgen.Generate(info); 461 if (cgen.HasStackOverflow()) { 462 ASSERT(!Top::has_pending_exception()); 463 return Handle<Code>::null(); 464 } 465 466 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); 467 return CodeGenerator::MakeCodeEpilogue(&masm, flags, info); 468 } 469 470 471 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { 472 UNREACHABLE(); 473 } 474 475 476 void FastCodeGenerator::VisitBlock(Block* stmt) { 477 VisitStatements(stmt->statements()); 478 } 479 480 481 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 482 Visit(stmt->expression()); 483 } 484 485 486 void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 487 // Nothing to do. 488 } 489 490 491 void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) { 492 UNREACHABLE(); 493 } 494 495 496 void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { 497 UNREACHABLE(); 498 } 499 500 501 void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 502 UNREACHABLE(); 503 } 504 505 506 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 507 UNREACHABLE(); 508 } 509 510 511 void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { 512 UNREACHABLE(); 513 } 514 515 516 void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { 517 UNREACHABLE(); 518 } 519 520 521 void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 522 UNREACHABLE(); 523 } 524 525 526 void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 527 UNREACHABLE(); 528 } 529 530 531 void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 532 UNREACHABLE(); 533 } 534 535 536 void FastCodeGenerator::VisitForStatement(ForStatement* stmt) { 537 UNREACHABLE(); 538 } 539 540 541 void FastCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 542 UNREACHABLE(); 543 } 544 545 546 void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { 547 UNREACHABLE(); 548 } 549 550 551 void FastCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 552 UNREACHABLE(); 553 } 554 555 556 void FastCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { 557 UNREACHABLE(); 558 } 559 560 561 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 562 UNREACHABLE(); 563 } 564 565 566 void FastCodeGenerator::VisitFunctionBoilerplateLiteral( 567 FunctionBoilerplateLiteral* expr) { 568 UNREACHABLE(); 569 } 570 571 572 void FastCodeGenerator::VisitConditional(Conditional* expr) { 573 UNREACHABLE(); 574 } 575 576 577 void FastCodeGenerator::VisitSlot(Slot* expr) { 578 UNREACHABLE(); 579 } 580 581 582 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 583 ASSERT(expr->var()->is_global() && !expr->var()->is_this()); 584 // Check if we can compile a global variable load directly from the cell. 585 ASSERT(info()->has_global_object()); 586 LookupResult lookup; 587 info()->global_object()->Lookup(*expr->name(), &lookup); 588 // We only support normal (non-accessor/interceptor) DontDelete properties 589 // for now. 590 ASSERT(lookup.IsProperty()); 591 ASSERT_EQ(NORMAL, lookup.type()); 592 ASSERT(lookup.IsDontDelete()); 593 Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup)); 594 595 // Global variable lookups do not have side effects, so we do not need to 596 // emit code if we are in an effect context. 597 if (!destination().is(no_reg)) { 598 Comment cmnt(masm(), ";; Global"); 599 if (FLAG_print_ir) { 600 SmartPointer<char> name = expr->name()->ToCString(); 601 PrintF("%d: t%d = Global(%s) // last_use = %d\n", expr->num(), 602 expr->num(), *name, expr->var_def()->last_use()->num()); 603 } 604 EmitGlobalVariableLoad(cell); 605 } 606 } 607 608 609 void FastCodeGenerator::VisitLiteral(Literal* expr) { 610 UNREACHABLE(); 611 } 612 613 614 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 615 UNREACHABLE(); 616 } 617 618 619 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 620 UNREACHABLE(); 621 } 622 623 624 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 625 UNREACHABLE(); 626 } 627 628 629 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { 630 UNREACHABLE(); 631 } 632 633 634 void FastCodeGenerator::VisitAssignment(Assignment* expr) { 635 // Known to be a simple this property assignment. Effectively a unary 636 // operation. 637 { Register my_destination = destination(); 638 set_destination(accumulator0()); 639 Visit(expr->value()); 640 set_destination(my_destination); 641 } 642 643 Property* prop = expr->target()->AsProperty(); 644 ASSERT_NOT_NULL(prop); 645 ASSERT_NOT_NULL(prop->obj()->AsVariableProxy()); 646 ASSERT(prop->obj()->AsVariableProxy()->var()->is_this()); 647 ASSERT(prop->key()->IsPropertyName()); 648 Handle<String> name = 649 Handle<String>::cast(prop->key()->AsLiteral()->handle()); 650 651 Comment cmnt(masm(), ";; Store to this"); 652 if (FLAG_print_ir) { 653 SmartPointer<char> name_string = name->ToCString(); 654 PrintF("%d: ", expr->num()); 655 if (!destination().is(no_reg)) PrintF("t%d = ", expr->num()); 656 PrintF("Store(this, \"%s\", t%d) // last_use(this) = %d\n", *name_string, 657 expr->value()->num(), 658 expr->var_def()->last_use()->num()); 659 } 660 661 EmitThisPropertyStore(name); 662 } 663 664 665 void FastCodeGenerator::VisitThrow(Throw* expr) { 666 UNREACHABLE(); 667 } 668 669 670 void FastCodeGenerator::VisitProperty(Property* expr) { 671 ASSERT_NOT_NULL(expr->obj()->AsVariableProxy()); 672 ASSERT(expr->obj()->AsVariableProxy()->var()->is_this()); 673 ASSERT(expr->key()->IsPropertyName()); 674 if (!destination().is(no_reg)) { 675 Handle<String> name = 676 Handle<String>::cast(expr->key()->AsLiteral()->handle()); 677 678 Comment cmnt(masm(), ";; Load from this"); 679 if (FLAG_print_ir) { 680 SmartPointer<char> name_string = name->ToCString(); 681 PrintF("%d: t%d = Load(this, \"%s\") // last_use(this) = %d\n", 682 expr->num(), expr->num(), *name_string, 683 expr->var_def()->last_use()->num()); 684 } 685 EmitThisPropertyLoad(name); 686 } 687 } 688 689 690 void FastCodeGenerator::VisitCall(Call* expr) { 691 UNREACHABLE(); 692 } 693 694 695 void FastCodeGenerator::VisitCallNew(CallNew* expr) { 696 UNREACHABLE(); 697 } 698 699 700 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 701 UNREACHABLE(); 702 } 703 704 705 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 706 UNREACHABLE(); 707 } 708 709 710 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 711 UNREACHABLE(); 712 } 713 714 715 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 716 // We support limited binary operations: bitwise OR only allowed to be 717 // nested on the left. 718 ASSERT(expr->op() == Token::BIT_OR); 719 ASSERT(expr->right()->IsLeaf()); 720 721 { Register my_destination = destination(); 722 set_destination(accumulator1()); 723 Visit(expr->left()); 724 set_destination(accumulator0()); 725 Visit(expr->right()); 726 set_destination(my_destination); 727 } 728 729 Comment cmnt(masm(), ";; BIT_OR"); 730 if (FLAG_print_ir) { 731 PrintF("%d: ", expr->num()); 732 if (!destination().is(no_reg)) PrintF("t%d = ", expr->num()); 733 PrintF("BIT_OR(t%d, t%d)\n", expr->left()->num(), expr->right()->num()); 734 } 735 EmitBitOr(); 736 } 737 738 739 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 740 UNREACHABLE(); 741 } 742 743 744 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { 745 UNREACHABLE(); 746 } 747 748 #undef __ 749 750 751 } } // namespace v8::internal 752