Home | History | Annotate | Download | only in src
      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