| 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 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 #include "codegen-inl.h" | 30 #include "codegen-inl.h" |
| 31 #include "compiler.h" | 31 #include "compiler.h" |
| 32 #include "fast-codegen.h" | 32 #include "fast-codegen.h" |
| 33 #include "stub-cache.h" | 33 #include "stub-cache.h" |
| 34 #include "debug.h" | 34 #include "debug.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 #define BAILOUT(reason) \ |
| 40 do { \ |
| 41 if (FLAG_trace_bailout) { \ |
| 42 PrintF("%s\n", reason); \ |
| 43 } \ |
| 44 has_supported_syntax_ = false; \ |
| 45 return; \ |
| 46 } while (false) |
| 47 |
| 48 |
| 49 #define CHECK_BAILOUT \ |
| 50 do { \ |
| 51 if (!has_supported_syntax_) return; \ |
| 52 } while (false) |
| 53 |
| 54 |
| 55 void FullCodeGenSyntaxChecker::Check(FunctionLiteral* fun) { |
| 56 Scope* scope = fun->scope(); |
| 57 |
| 58 if (scope->num_heap_slots() > 0) { |
| 59 // We support functions with a local context if they do not have |
| 60 // parameters that need to be copied into the context. |
| 61 for (int i = 0, len = scope->num_parameters(); i < len; i++) { |
| 62 Slot* slot = scope->parameter(i)->slot(); |
| 63 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 64 BAILOUT("Function has context-allocated parameters."); |
| 65 } |
| 66 } |
| 67 } |
| 68 |
| 69 VisitDeclarations(scope->declarations()); |
| 70 CHECK_BAILOUT; |
| 71 |
| 72 VisitStatements(fun->body()); |
| 73 } |
| 74 |
| 75 |
| 76 void FullCodeGenSyntaxChecker::VisitDeclarations( |
| 77 ZoneList<Declaration*>* decls) { |
| 78 for (int i = 0; i < decls->length(); i++) { |
| 79 Visit(decls->at(i)); |
| 80 CHECK_BAILOUT; |
| 81 } |
| 82 } |
| 83 |
| 84 |
| 85 void FullCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) { |
| 86 for (int i = 0, len = stmts->length(); i < len; i++) { |
| 87 Visit(stmts->at(i)); |
| 88 CHECK_BAILOUT; |
| 89 } |
| 90 } |
| 91 |
| 92 |
| 93 void FullCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) { |
| 94 Property* prop = decl->proxy()->AsProperty(); |
| 95 if (prop != NULL) { |
| 96 Visit(prop->obj()); |
| 97 Visit(prop->key()); |
| 98 } |
| 99 |
| 100 if (decl->fun() != NULL) { |
| 101 Visit(decl->fun()); |
| 102 } |
| 103 } |
| 104 |
| 105 |
| 106 void FullCodeGenSyntaxChecker::VisitBlock(Block* stmt) { |
| 107 VisitStatements(stmt->statements()); |
| 108 } |
| 109 |
| 110 |
| 111 void FullCodeGenSyntaxChecker::VisitExpressionStatement( |
| 112 ExpressionStatement* stmt) { |
| 113 Visit(stmt->expression()); |
| 114 } |
| 115 |
| 116 |
| 117 void FullCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) { |
| 118 // Supported. |
| 119 } |
| 120 |
| 121 |
| 122 void FullCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) { |
| 123 Visit(stmt->condition()); |
| 124 CHECK_BAILOUT; |
| 125 Visit(stmt->then_statement()); |
| 126 CHECK_BAILOUT; |
| 127 Visit(stmt->else_statement()); |
| 128 } |
| 129 |
| 130 |
| 131 void FullCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) { |
| 132 // Supported. |
| 133 } |
| 134 |
| 135 |
| 136 void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) {} |
| 137 |
| 138 |
| 139 void FullCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) { |
| 140 Visit(stmt->expression()); |
| 141 } |
| 142 |
| 143 |
| 144 void FullCodeGenSyntaxChecker::VisitWithEnterStatement( |
| 145 WithEnterStatement* stmt) { |
| 146 Visit(stmt->expression()); |
| 147 } |
| 148 |
| 149 |
| 150 void FullCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) { |
| 151 // Supported. |
| 152 } |
| 153 |
| 154 |
| 155 void FullCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) { |
| 156 BAILOUT("SwitchStatement"); |
| 157 } |
| 158 |
| 159 |
| 160 void FullCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 161 Visit(stmt->cond()); |
| 162 CHECK_BAILOUT; |
| 163 Visit(stmt->body()); |
| 164 } |
| 165 |
| 166 |
| 167 void FullCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) { |
| 168 Visit(stmt->cond()); |
| 169 CHECK_BAILOUT; |
| 170 Visit(stmt->body()); |
| 171 } |
| 172 |
| 173 |
| 174 void FullCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) { |
| 175 BAILOUT("ForStatement"); |
| 176 } |
| 177 |
| 178 |
| 179 void FullCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) { |
| 180 BAILOUT("ForInStatement"); |
| 181 } |
| 182 |
| 183 |
| 184 void FullCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 185 Visit(stmt->try_block()); |
| 186 CHECK_BAILOUT; |
| 187 Visit(stmt->catch_block()); |
| 188 } |
| 189 |
| 190 |
| 191 void FullCodeGenSyntaxChecker::VisitTryFinallyStatement( |
| 192 TryFinallyStatement* stmt) { |
| 193 Visit(stmt->try_block()); |
| 194 CHECK_BAILOUT; |
| 195 Visit(stmt->finally_block()); |
| 196 } |
| 197 |
| 198 |
| 199 void FullCodeGenSyntaxChecker::VisitDebuggerStatement( |
| 200 DebuggerStatement* stmt) { |
| 201 // Supported. |
| 202 } |
| 203 |
| 204 |
| 205 void FullCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 206 // Supported. |
| 207 } |
| 208 |
| 209 |
| 210 void FullCodeGenSyntaxChecker::VisitFunctionBoilerplateLiteral( |
| 211 FunctionBoilerplateLiteral* expr) { |
| 212 BAILOUT("FunctionBoilerplateLiteral"); |
| 213 } |
| 214 |
| 215 |
| 216 void FullCodeGenSyntaxChecker::VisitConditional(Conditional* expr) { |
| 217 Visit(expr->condition()); |
| 218 CHECK_BAILOUT; |
| 219 Visit(expr->then_expression()); |
| 220 CHECK_BAILOUT; |
| 221 Visit(expr->else_expression()); |
| 222 } |
| 223 |
| 224 |
| 225 void FullCodeGenSyntaxChecker::VisitSlot(Slot* expr) { |
| 226 UNREACHABLE(); |
| 227 } |
| 228 |
| 229 |
| 230 void FullCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) { |
| 231 Variable* var = expr->var(); |
| 232 if (!var->is_global()) { |
| 233 Slot* slot = var->slot(); |
| 234 if (slot != NULL) { |
| 235 Slot::Type type = slot->type(); |
| 236 // When LOOKUP slots are enabled, some currently dead code |
| 237 // implementing unary typeof will become live. |
| 238 if (type == Slot::LOOKUP) { |
| 239 BAILOUT("Lookup slot"); |
| 240 } |
| 241 } else { |
| 242 // If not global or a slot, it is a parameter rewritten to an explicit |
| 243 // property reference on the (shadow) arguments object. |
| 244 #ifdef DEBUG |
| 245 Property* property = var->AsProperty(); |
| 246 ASSERT_NOT_NULL(property); |
| 247 Variable* object = property->obj()->AsVariableProxy()->AsVariable(); |
| 248 ASSERT_NOT_NULL(object); |
| 249 ASSERT_NOT_NULL(object->slot()); |
| 250 ASSERT_NOT_NULL(property->key()->AsLiteral()); |
| 251 ASSERT(property->key()->AsLiteral()->handle()->IsSmi()); |
| 252 #endif |
| 253 } |
| 254 } |
| 255 } |
| 256 |
| 257 |
| 258 void FullCodeGenSyntaxChecker::VisitLiteral(Literal* expr) { |
| 259 // Supported. |
| 260 } |
| 261 |
| 262 |
| 263 void FullCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 264 // Supported. |
| 265 } |
| 266 |
| 267 |
| 268 void FullCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) { |
| 269 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); |
| 270 |
| 271 for (int i = 0, len = properties->length(); i < len; i++) { |
| 272 ObjectLiteral::Property* property = properties->at(i); |
| 273 if (property->IsCompileTimeValue()) continue; |
| 274 Visit(property->key()); |
| 275 CHECK_BAILOUT; |
| 276 Visit(property->value()); |
| 277 CHECK_BAILOUT; |
| 278 } |
| 279 } |
| 280 |
| 281 |
| 282 void FullCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) { |
| 283 ZoneList<Expression*>* subexprs = expr->values(); |
| 284 for (int i = 0, len = subexprs->length(); i < len; i++) { |
| 285 Expression* subexpr = subexprs->at(i); |
| 286 if (subexpr->AsLiteral() != NULL) continue; |
| 287 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 288 Visit(subexpr); |
| 289 CHECK_BAILOUT; |
| 290 } |
| 291 } |
| 292 |
| 293 |
| 294 void FullCodeGenSyntaxChecker::VisitCatchExtensionObject( |
| 295 CatchExtensionObject* expr) { |
| 296 Visit(expr->key()); |
| 297 CHECK_BAILOUT; |
| 298 Visit(expr->value()); |
| 299 } |
| 300 |
| 301 |
| 302 void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) { |
| 303 // We support plain non-compound assignments to properties, parameters and |
| 304 // non-context (stack-allocated) locals, and global variables. |
| 305 Token::Value op = expr->op(); |
| 306 if (op == Token::INIT_CONST) BAILOUT("initialize constant"); |
| 307 |
| 308 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
| 309 Property* prop = expr->target()->AsProperty(); |
| 310 ASSERT(var == NULL || prop == NULL); |
| 311 if (var != NULL) { |
| 312 if (var->mode() == Variable::CONST) { |
| 313 BAILOUT("Assignment to const"); |
| 314 } |
| 315 // All global variables are supported. |
| 316 if (!var->is_global()) { |
| 317 ASSERT(var->slot() != NULL); |
| 318 Slot::Type type = var->slot()->type(); |
| 319 if (type == Slot::LOOKUP) { |
| 320 BAILOUT("Lookup slot"); |
| 321 } |
| 322 } |
| 323 } else if (prop != NULL) { |
| 324 Visit(prop->obj()); |
| 325 CHECK_BAILOUT; |
| 326 Visit(prop->key()); |
| 327 CHECK_BAILOUT; |
| 328 } else { |
| 329 // This is a throw reference error. |
| 330 BAILOUT("non-variable/non-property assignment"); |
| 331 } |
| 332 |
| 333 Visit(expr->value()); |
| 334 } |
| 335 |
| 336 |
| 337 void FullCodeGenSyntaxChecker::VisitThrow(Throw* expr) { |
| 338 Visit(expr->exception()); |
| 339 } |
| 340 |
| 341 |
| 342 void FullCodeGenSyntaxChecker::VisitProperty(Property* expr) { |
| 343 Visit(expr->obj()); |
| 344 CHECK_BAILOUT; |
| 345 Visit(expr->key()); |
| 346 } |
| 347 |
| 348 |
| 349 void FullCodeGenSyntaxChecker::VisitCall(Call* expr) { |
| 350 Expression* fun = expr->expression(); |
| 351 ZoneList<Expression*>* args = expr->arguments(); |
| 352 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 353 |
| 354 // Check for supported calls |
| 355 if (var != NULL && var->is_possibly_eval()) { |
| 356 BAILOUT("call to the identifier 'eval'"); |
| 357 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 358 // Calls to global variables are supported. |
| 359 } else if (var != NULL && var->slot() != NULL && |
| 360 var->slot()->type() == Slot::LOOKUP) { |
| 361 BAILOUT("call to a lookup slot"); |
| 362 } else if (fun->AsProperty() != NULL) { |
| 363 Property* prop = fun->AsProperty(); |
| 364 Visit(prop->obj()); |
| 365 CHECK_BAILOUT; |
| 366 Visit(prop->key()); |
| 367 CHECK_BAILOUT; |
| 368 } else { |
| 369 // Otherwise the call is supported if the function expression is. |
| 370 Visit(fun); |
| 371 } |
| 372 // Check all arguments to the call. |
| 373 for (int i = 0; i < args->length(); i++) { |
| 374 Visit(args->at(i)); |
| 375 CHECK_BAILOUT; |
| 376 } |
| 377 } |
| 378 |
| 379 |
| 380 void FullCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { |
| 381 Visit(expr->expression()); |
| 382 CHECK_BAILOUT; |
| 383 ZoneList<Expression*>* args = expr->arguments(); |
| 384 // Check all arguments to the call |
| 385 for (int i = 0; i < args->length(); i++) { |
| 386 Visit(args->at(i)); |
| 387 CHECK_BAILOUT; |
| 388 } |
| 389 } |
| 390 |
| 391 |
| 392 void FullCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { |
| 393 // Check for inline runtime call |
| 394 if (expr->name()->Get(0) == '_' && |
| 395 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { |
| 396 BAILOUT("inlined runtime call"); |
| 397 } |
| 398 // Check all arguments to the call. (Relies on TEMP meaning STACK.) |
| 399 for (int i = 0; i < expr->arguments()->length(); i++) { |
| 400 Visit(expr->arguments()->at(i)); |
| 401 CHECK_BAILOUT; |
| 402 } |
| 403 } |
| 404 |
| 405 |
| 406 void FullCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { |
| 407 switch (expr->op()) { |
| 408 case Token::VOID: |
| 409 case Token::NOT: |
| 410 case Token::TYPEOF: |
| 411 Visit(expr->expression()); |
| 412 break; |
| 413 case Token::BIT_NOT: |
| 414 BAILOUT("UnaryOperation: BIT_NOT"); |
| 415 case Token::DELETE: |
| 416 BAILOUT("UnaryOperation: DELETE"); |
| 417 case Token::ADD: |
| 418 BAILOUT("UnaryOperation: ADD"); |
| 419 case Token::SUB: |
| 420 BAILOUT("UnaryOperation: SUB"); |
| 421 default: |
| 422 UNREACHABLE(); |
| 423 } |
| 424 } |
| 425 |
| 426 |
| 427 void FullCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { |
| 428 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 429 Property* prop = expr->expression()->AsProperty(); |
| 430 ASSERT(var == NULL || prop == NULL); |
| 431 if (var != NULL) { |
| 432 // All global variables are supported. |
| 433 if (!var->is_global()) { |
| 434 ASSERT(var->slot() != NULL); |
| 435 Slot::Type type = var->slot()->type(); |
| 436 if (type == Slot::LOOKUP) { |
| 437 BAILOUT("CountOperation with lookup slot"); |
| 438 } |
| 439 } |
| 440 } else if (prop != NULL) { |
| 441 Visit(prop->obj()); |
| 442 CHECK_BAILOUT; |
| 443 Visit(prop->key()); |
| 444 CHECK_BAILOUT; |
| 445 } else { |
| 446 // This is a throw reference error. |
| 447 BAILOUT("CountOperation non-variable/non-property expression"); |
| 448 } |
| 449 } |
| 450 |
| 451 |
| 452 void FullCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { |
| 453 Visit(expr->left()); |
| 454 CHECK_BAILOUT; |
| 455 Visit(expr->right()); |
| 456 } |
| 457 |
| 458 |
| 459 void FullCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { |
| 460 Visit(expr->left()); |
| 461 CHECK_BAILOUT; |
| 462 Visit(expr->right()); |
| 463 } |
| 464 |
| 465 |
| 466 void FullCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { |
| 467 // Supported. |
| 468 } |
| 469 |
| 470 #undef BAILOUT |
| 471 #undef CHECK_BAILOUT |
| 472 |
| 473 |
| 39 #define __ ACCESS_MASM(masm()) | 474 #define __ ACCESS_MASM(masm()) |
| 40 | 475 |
| 41 Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun, | 476 Handle<Code> FullCodeGenerator::MakeCode(FunctionLiteral* fun, |
| 42 Handle<Script> script, | 477 Handle<Script> script, |
| 43 bool is_eval) { | 478 bool is_eval) { |
| 44 CodeGenerator::MakeCodePrologue(fun); | 479 CodeGenerator::MakeCodePrologue(fun); |
| 45 const int kInitialBufferSize = 4 * KB; | 480 const int kInitialBufferSize = 4 * KB; |
| 46 MacroAssembler masm(NULL, kInitialBufferSize); | 481 MacroAssembler masm(NULL, kInitialBufferSize); |
| 47 FastCodeGenerator cgen(&masm, script, is_eval); | 482 FullCodeGenerator cgen(&masm, script, is_eval); |
| 48 cgen.Generate(fun); | 483 cgen.Generate(fun); |
| 49 if (cgen.HasStackOverflow()) { | 484 if (cgen.HasStackOverflow()) { |
| 50 ASSERT(!Top::has_pending_exception()); | 485 ASSERT(!Top::has_pending_exception()); |
| 51 return Handle<Code>::null(); | 486 return Handle<Code>::null(); |
| 52 } | 487 } |
| 53 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); | 488 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); |
| 54 return CodeGenerator::MakeCodeEpilogue(fun, &masm, flags, script); | 489 return CodeGenerator::MakeCodeEpilogue(fun, &masm, flags, script); |
| 55 } | 490 } |
| 56 | 491 |
| 57 | 492 |
| 58 int FastCodeGenerator::SlotOffset(Slot* slot) { | 493 int FullCodeGenerator::SlotOffset(Slot* slot) { |
| 59 ASSERT(slot != NULL); | 494 ASSERT(slot != NULL); |
| 60 // Offset is negative because higher indexes are at lower addresses. | 495 // Offset is negative because higher indexes are at lower addresses. |
| 61 int offset = -slot->index() * kPointerSize; | 496 int offset = -slot->index() * kPointerSize; |
| 62 // Adjust by a (parameter or local) base offset. | 497 // Adjust by a (parameter or local) base offset. |
| 63 switch (slot->type()) { | 498 switch (slot->type()) { |
| 64 case Slot::PARAMETER: | 499 case Slot::PARAMETER: |
| 65 offset += (function_->scope()->num_parameters() + 1) * kPointerSize; | 500 offset += (function_->scope()->num_parameters() + 1) * kPointerSize; |
| 66 break; | 501 break; |
| 67 case Slot::LOCAL: | 502 case Slot::LOCAL: |
| 68 offset += JavaScriptFrameConstants::kLocal0Offset; | 503 offset += JavaScriptFrameConstants::kLocal0Offset; |
| 69 break; | 504 break; |
| 70 case Slot::CONTEXT: | 505 case Slot::CONTEXT: |
| 71 case Slot::LOOKUP: | 506 case Slot::LOOKUP: |
| 72 UNREACHABLE(); | 507 UNREACHABLE(); |
| 73 } | 508 } |
| 74 return offset; | 509 return offset; |
| 75 } | 510 } |
| 76 | 511 |
| 77 | 512 |
| 78 void FastCodeGenerator::VisitDeclarations( | 513 void FullCodeGenerator::VisitDeclarations( |
| 79 ZoneList<Declaration*>* declarations) { | 514 ZoneList<Declaration*>* declarations) { |
| 80 int length = declarations->length(); | 515 int length = declarations->length(); |
| 81 int globals = 0; | 516 int globals = 0; |
| 82 for (int i = 0; i < length; i++) { | 517 for (int i = 0; i < length; i++) { |
| 83 Declaration* decl = declarations->at(i); | 518 Declaration* decl = declarations->at(i); |
| 84 Variable* var = decl->proxy()->var(); | 519 Variable* var = decl->proxy()->var(); |
| 85 Slot* slot = var->slot(); | 520 Slot* slot = var->slot(); |
| 86 | 521 |
| 87 // If it was not possible to allocate the variable at compile | 522 // If it was not possible to allocate the variable at compile |
| 88 // time, we need to "declare" it at runtime to make sure it | 523 // time, we need to "declare" it at runtime to make sure it |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 } | 557 } |
| 123 } | 558 } |
| 124 } | 559 } |
| 125 // Invoke the platform-dependent code generator to do the actual | 560 // Invoke the platform-dependent code generator to do the actual |
| 126 // declaration the global variables and functions. | 561 // declaration the global variables and functions. |
| 127 DeclareGlobals(array); | 562 DeclareGlobals(array); |
| 128 } | 563 } |
| 129 } | 564 } |
| 130 | 565 |
| 131 | 566 |
| 132 void FastCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { | 567 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { |
| 133 if (FLAG_debug_info) { | 568 if (FLAG_debug_info) { |
| 134 CodeGenerator::RecordPositions(masm_, fun->start_position()); | 569 CodeGenerator::RecordPositions(masm_, fun->start_position()); |
| 135 } | 570 } |
| 136 } | 571 } |
| 137 | 572 |
| 138 | 573 |
| 139 void FastCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { | 574 void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { |
| 140 if (FLAG_debug_info) { | 575 if (FLAG_debug_info) { |
| 141 CodeGenerator::RecordPositions(masm_, fun->end_position()); | 576 CodeGenerator::RecordPositions(masm_, fun->end_position()); |
| 142 } | 577 } |
| 143 } | 578 } |
| 144 | 579 |
| 145 | 580 |
| 146 void FastCodeGenerator::SetStatementPosition(Statement* stmt) { | 581 void FullCodeGenerator::SetStatementPosition(Statement* stmt) { |
| 147 if (FLAG_debug_info) { | 582 if (FLAG_debug_info) { |
| 148 CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); | 583 CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); |
| 149 } | 584 } |
| 150 } | 585 } |
| 151 | 586 |
| 152 | 587 |
| 153 void FastCodeGenerator::SetStatementPosition(int pos) { | 588 void FullCodeGenerator::SetStatementPosition(int pos) { |
| 154 if (FLAG_debug_info) { | 589 if (FLAG_debug_info) { |
| 155 CodeGenerator::RecordPositions(masm_, pos); | 590 CodeGenerator::RecordPositions(masm_, pos); |
| 156 } | 591 } |
| 157 } | 592 } |
| 158 | 593 |
| 159 | 594 |
| 160 void FastCodeGenerator::SetSourcePosition(int pos) { | 595 void FullCodeGenerator::SetSourcePosition(int pos) { |
| 161 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { | 596 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { |
| 162 masm_->RecordPosition(pos); | 597 masm_->RecordPosition(pos); |
| 163 } | 598 } |
| 164 } | 599 } |
| 165 | 600 |
| 166 | 601 |
| 167 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { | 602 void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { |
| 168 Label eval_right, done; | 603 Label eval_right, done; |
| 169 | 604 |
| 170 // Set up the appropriate context for the left subexpression based | 605 // Set up the appropriate context for the left subexpression based |
| 171 // on the operation and our own context. Initially assume we can | 606 // on the operation and our own context. Initially assume we can |
| 172 // inherit both true and false labels from our context. | 607 // inherit both true and false labels from our context. |
| 173 if (expr->op() == Token::OR) { | 608 if (expr->op() == Token::OR) { |
| 174 switch (context_) { | 609 switch (context_) { |
| 175 case Expression::kUninitialized: | 610 case Expression::kUninitialized: |
| 176 UNREACHABLE(); | 611 UNREACHABLE(); |
| 177 case Expression::kEffect: | 612 case Expression::kEffect: |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 } | 660 } |
| 226 } | 661 } |
| 227 | 662 |
| 228 __ bind(&eval_right); | 663 __ bind(&eval_right); |
| 229 Visit(expr->right()); | 664 Visit(expr->right()); |
| 230 | 665 |
| 231 __ bind(&done); | 666 __ bind(&done); |
| 232 } | 667 } |
| 233 | 668 |
| 234 | 669 |
| 235 void FastCodeGenerator::VisitBlock(Block* stmt) { | 670 void FullCodeGenerator::VisitBlock(Block* stmt) { |
| 236 Comment cmnt(masm_, "[ Block"); | 671 Comment cmnt(masm_, "[ Block"); |
| 237 Breakable nested_statement(this, stmt); | 672 Breakable nested_statement(this, stmt); |
| 238 SetStatementPosition(stmt); | 673 SetStatementPosition(stmt); |
| 239 VisitStatements(stmt->statements()); | 674 VisitStatements(stmt->statements()); |
| 240 __ bind(nested_statement.break_target()); | 675 __ bind(nested_statement.break_target()); |
| 241 } | 676 } |
| 242 | 677 |
| 243 | 678 |
| 244 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 679 void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 245 Comment cmnt(masm_, "[ ExpressionStatement"); | 680 Comment cmnt(masm_, "[ ExpressionStatement"); |
| 246 SetStatementPosition(stmt); | 681 SetStatementPosition(stmt); |
| 247 VisitForEffect(stmt->expression()); | 682 VisitForEffect(stmt->expression()); |
| 248 } | 683 } |
| 249 | 684 |
| 250 | 685 |
| 251 void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 686 void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
| 252 Comment cmnt(masm_, "[ EmptyStatement"); | 687 Comment cmnt(masm_, "[ EmptyStatement"); |
| 253 SetStatementPosition(stmt); | 688 SetStatementPosition(stmt); |
| 254 } | 689 } |
| 255 | 690 |
| 256 | 691 |
| 257 void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) { | 692 void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) { |
| 258 Comment cmnt(masm_, "[ IfStatement"); | 693 Comment cmnt(masm_, "[ IfStatement"); |
| 259 SetStatementPosition(stmt); | 694 SetStatementPosition(stmt); |
| 260 Label then_part, else_part, done; | 695 Label then_part, else_part, done; |
| 261 | 696 |
| 262 // Do not worry about optimizing for empty then or else bodies. | 697 // Do not worry about optimizing for empty then or else bodies. |
| 263 VisitForControl(stmt->condition(), &then_part, &else_part); | 698 VisitForControl(stmt->condition(), &then_part, &else_part); |
| 264 | 699 |
| 265 __ bind(&then_part); | 700 __ bind(&then_part); |
| 266 Visit(stmt->then_statement()); | 701 Visit(stmt->then_statement()); |
| 267 __ jmp(&done); | 702 __ jmp(&done); |
| 268 | 703 |
| 269 __ bind(&else_part); | 704 __ bind(&else_part); |
| 270 Visit(stmt->else_statement()); | 705 Visit(stmt->else_statement()); |
| 271 | 706 |
| 272 __ bind(&done); | 707 __ bind(&done); |
| 273 } | 708 } |
| 274 | 709 |
| 275 | 710 |
| 276 void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 711 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { |
| 277 Comment cmnt(masm_, "[ ContinueStatement"); | 712 Comment cmnt(masm_, "[ ContinueStatement"); |
| 278 SetStatementPosition(stmt); | 713 SetStatementPosition(stmt); |
| 279 NestedStatement* current = nesting_stack_; | 714 NestedStatement* current = nesting_stack_; |
| 280 int stack_depth = 0; | 715 int stack_depth = 0; |
| 281 while (!current->IsContinueTarget(stmt->target())) { | 716 while (!current->IsContinueTarget(stmt->target())) { |
| 282 stack_depth = current->Exit(stack_depth); | 717 stack_depth = current->Exit(stack_depth); |
| 283 current = current->outer(); | 718 current = current->outer(); |
| 284 } | 719 } |
| 285 __ Drop(stack_depth); | 720 __ Drop(stack_depth); |
| 286 | 721 |
| 287 Iteration* loop = current->AsIteration(); | 722 Iteration* loop = current->AsIteration(); |
| 288 __ jmp(loop->continue_target()); | 723 __ jmp(loop->continue_target()); |
| 289 } | 724 } |
| 290 | 725 |
| 291 | 726 |
| 292 void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 727 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
| 293 Comment cmnt(masm_, "[ BreakStatement"); | 728 Comment cmnt(masm_, "[ BreakStatement"); |
| 294 SetStatementPosition(stmt); | 729 SetStatementPosition(stmt); |
| 295 NestedStatement* current = nesting_stack_; | 730 NestedStatement* current = nesting_stack_; |
| 296 int stack_depth = 0; | 731 int stack_depth = 0; |
| 297 while (!current->IsBreakTarget(stmt->target())) { | 732 while (!current->IsBreakTarget(stmt->target())) { |
| 298 stack_depth = current->Exit(stack_depth); | 733 stack_depth = current->Exit(stack_depth); |
| 299 current = current->outer(); | 734 current = current->outer(); |
| 300 } | 735 } |
| 301 __ Drop(stack_depth); | 736 __ Drop(stack_depth); |
| 302 | 737 |
| 303 Breakable* target = current->AsBreakable(); | 738 Breakable* target = current->AsBreakable(); |
| 304 __ jmp(target->break_target()); | 739 __ jmp(target->break_target()); |
| 305 } | 740 } |
| 306 | 741 |
| 307 | 742 |
| 308 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 743 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
| 309 Comment cmnt(masm_, "[ ReturnStatement"); | 744 Comment cmnt(masm_, "[ ReturnStatement"); |
| 310 SetStatementPosition(stmt); | 745 SetStatementPosition(stmt); |
| 311 Expression* expr = stmt->expression(); | 746 Expression* expr = stmt->expression(); |
| 312 VisitForValue(expr, kAccumulator); | 747 VisitForValue(expr, kAccumulator); |
| 313 | 748 |
| 314 // Exit all nested statements. | 749 // Exit all nested statements. |
| 315 NestedStatement* current = nesting_stack_; | 750 NestedStatement* current = nesting_stack_; |
| 316 int stack_depth = 0; | 751 int stack_depth = 0; |
| 317 while (current != NULL) { | 752 while (current != NULL) { |
| 318 stack_depth = current->Exit(stack_depth); | 753 stack_depth = current->Exit(stack_depth); |
| 319 current = current->outer(); | 754 current = current->outer(); |
| 320 } | 755 } |
| 321 __ Drop(stack_depth); | 756 __ Drop(stack_depth); |
| 322 | 757 |
| 323 EmitReturnSequence(stmt->statement_pos()); | 758 EmitReturnSequence(stmt->statement_pos()); |
| 324 } | 759 } |
| 325 | 760 |
| 326 | 761 |
| 327 void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { | 762 void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { |
| 328 Comment cmnt(masm_, "[ WithEnterStatement"); | 763 Comment cmnt(masm_, "[ WithEnterStatement"); |
| 329 SetStatementPosition(stmt); | 764 SetStatementPosition(stmt); |
| 330 | 765 |
| 331 VisitForValue(stmt->expression(), kStack); | 766 VisitForValue(stmt->expression(), kStack); |
| 332 if (stmt->is_catch_block()) { | 767 if (stmt->is_catch_block()) { |
| 333 __ CallRuntime(Runtime::kPushCatchContext, 1); | 768 __ CallRuntime(Runtime::kPushCatchContext, 1); |
| 334 } else { | 769 } else { |
| 335 __ CallRuntime(Runtime::kPushContext, 1); | 770 __ CallRuntime(Runtime::kPushContext, 1); |
| 336 } | 771 } |
| 337 // Both runtime calls return the new context in both the context and the | 772 // Both runtime calls return the new context in both the context and the |
| 338 // result registers. | 773 // result registers. |
| 339 | 774 |
| 340 // Update local stack frame context field. | 775 // Update local stack frame context field. |
| 341 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 776 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 342 } | 777 } |
| 343 | 778 |
| 344 | 779 |
| 345 void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { | 780 void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { |
| 346 Comment cmnt(masm_, "[ WithExitStatement"); | 781 Comment cmnt(masm_, "[ WithExitStatement"); |
| 347 SetStatementPosition(stmt); | 782 SetStatementPosition(stmt); |
| 348 | 783 |
| 349 // Pop context. | 784 // Pop context. |
| 350 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 785 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 351 // Update local stack frame context field. | 786 // Update local stack frame context field. |
| 352 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 787 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 353 } | 788 } |
| 354 | 789 |
| 355 | 790 |
| 356 void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 791 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 357 UNREACHABLE(); | 792 UNREACHABLE(); |
| 358 } | 793 } |
| 359 | 794 |
| 360 | 795 |
| 361 void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 796 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 362 Comment cmnt(masm_, "[ DoWhileStatement"); | 797 Comment cmnt(masm_, "[ DoWhileStatement"); |
| 363 SetStatementPosition(stmt); | 798 SetStatementPosition(stmt); |
| 364 Label body, stack_limit_hit, stack_check_success; | 799 Label body, stack_limit_hit, stack_check_success; |
| 365 | 800 |
| 366 Iteration loop_statement(this, stmt); | 801 Iteration loop_statement(this, stmt); |
| 367 increment_loop_depth(); | 802 increment_loop_depth(); |
| 368 | 803 |
| 369 __ bind(&body); | 804 __ bind(&body); |
| 370 Visit(stmt->body()); | 805 Visit(stmt->body()); |
| 371 | 806 |
| 372 // Check stack before looping. | 807 // Check stack before looping. |
| 373 __ StackLimitCheck(&stack_limit_hit); | 808 __ StackLimitCheck(&stack_limit_hit); |
| 374 __ bind(&stack_check_success); | 809 __ bind(&stack_check_success); |
| 375 | 810 |
| 376 __ bind(loop_statement.continue_target()); | 811 __ bind(loop_statement.continue_target()); |
| 377 SetStatementPosition(stmt->condition_position()); | 812 SetStatementPosition(stmt->condition_position()); |
| 378 VisitForControl(stmt->cond(), &body, loop_statement.break_target()); | 813 VisitForControl(stmt->cond(), &body, loop_statement.break_target()); |
| 379 | 814 |
| 380 __ bind(&stack_limit_hit); | 815 __ bind(&stack_limit_hit); |
| 381 StackCheckStub stack_stub; | 816 StackCheckStub stack_stub; |
| 382 __ CallStub(&stack_stub); | 817 __ CallStub(&stack_stub); |
| 383 __ jmp(&stack_check_success); | 818 __ jmp(&stack_check_success); |
| 384 | 819 |
| 385 __ bind(loop_statement.break_target()); | 820 __ bind(loop_statement.break_target()); |
| 386 | 821 |
| 387 decrement_loop_depth(); | 822 decrement_loop_depth(); |
| 388 } | 823 } |
| 389 | 824 |
| 390 | 825 |
| 391 void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 826 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
| 392 Comment cmnt(masm_, "[ WhileStatement"); | 827 Comment cmnt(masm_, "[ WhileStatement"); |
| 393 SetStatementPosition(stmt); | 828 SetStatementPosition(stmt); |
| 394 Label body, stack_limit_hit, stack_check_success; | 829 Label body, stack_limit_hit, stack_check_success; |
| 395 | 830 |
| 396 Iteration loop_statement(this, stmt); | 831 Iteration loop_statement(this, stmt); |
| 397 increment_loop_depth(); | 832 increment_loop_depth(); |
| 398 | 833 |
| 399 // Emit the test at the bottom of the loop. | 834 // Emit the test at the bottom of the loop. |
| 400 __ jmp(loop_statement.continue_target()); | 835 __ jmp(loop_statement.continue_target()); |
| 401 | 836 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 412 __ bind(&stack_limit_hit); | 847 __ bind(&stack_limit_hit); |
| 413 StackCheckStub stack_stub; | 848 StackCheckStub stack_stub; |
| 414 __ CallStub(&stack_stub); | 849 __ CallStub(&stack_stub); |
| 415 __ jmp(&stack_check_success); | 850 __ jmp(&stack_check_success); |
| 416 | 851 |
| 417 __ bind(loop_statement.break_target()); | 852 __ bind(loop_statement.break_target()); |
| 418 decrement_loop_depth(); | 853 decrement_loop_depth(); |
| 419 } | 854 } |
| 420 | 855 |
| 421 | 856 |
| 422 void FastCodeGenerator::VisitForStatement(ForStatement* stmt) { | 857 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { |
| 423 UNREACHABLE(); | 858 UNREACHABLE(); |
| 424 } | 859 } |
| 425 | 860 |
| 426 | 861 |
| 427 void FastCodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 862 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 428 UNREACHABLE(); | 863 UNREACHABLE(); |
| 429 } | 864 } |
| 430 | 865 |
| 431 | 866 |
| 432 void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 867 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 433 Comment cmnt(masm_, "[ TryCatchStatement"); | 868 Comment cmnt(masm_, "[ TryCatchStatement"); |
| 434 SetStatementPosition(stmt); | 869 SetStatementPosition(stmt); |
| 435 // The try block adds a handler to the exception handler chain | 870 // The try block adds a handler to the exception handler chain |
| 436 // before entering, and removes it again when exiting normally. | 871 // before entering, and removes it again when exiting normally. |
| 437 // If an exception is thrown during execution of the try block, | 872 // If an exception is thrown during execution of the try block, |
| 438 // control is passed to the handler, which also consumes the handler. | 873 // control is passed to the handler, which also consumes the handler. |
| 439 // At this point, the exception is in a register, and store it in | 874 // At this point, the exception is in a register, and store it in |
| 440 // the temporary local variable (prints as ".catch-var") before | 875 // the temporary local variable (prints as ".catch-var") before |
| 441 // executing the catch block. The catch block has been rewritten | 876 // executing the catch block. The catch block has been rewritten |
| 442 // to introduce a new scope to bind the catch variable and to remove | 877 // to introduce a new scope to bind the catch variable and to remove |
| (...skipping 22 matching lines...) Expand all Loading... |
| 465 { | 900 { |
| 466 TryCatch try_block(this, &catch_entry); | 901 TryCatch try_block(this, &catch_entry); |
| 467 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); | 902 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); |
| 468 Visit(stmt->try_block()); | 903 Visit(stmt->try_block()); |
| 469 __ PopTryHandler(); | 904 __ PopTryHandler(); |
| 470 } | 905 } |
| 471 __ bind(&done); | 906 __ bind(&done); |
| 472 } | 907 } |
| 473 | 908 |
| 474 | 909 |
| 475 void FastCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 910 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 476 Comment cmnt(masm_, "[ TryFinallyStatement"); | 911 Comment cmnt(masm_, "[ TryFinallyStatement"); |
| 477 SetStatementPosition(stmt); | 912 SetStatementPosition(stmt); |
| 478 // Try finally is compiled by setting up a try-handler on the stack while | 913 // Try finally is compiled by setting up a try-handler on the stack while |
| 479 // executing the try body, and removing it again afterwards. | 914 // executing the try body, and removing it again afterwards. |
| 480 // | 915 // |
| 481 // The try-finally construct can enter the finally block in three ways: | 916 // The try-finally construct can enter the finally block in three ways: |
| 482 // 1. By exiting the try-block normally. This removes the try-handler and | 917 // 1. By exiting the try-block normally. This removes the try-handler and |
| 483 // calls the finally block code before continuing. | 918 // calls the finally block code before continuing. |
| 484 // 2. By exiting the try-block with a function-local control flow transfer | 919 // 2. By exiting the try-block with a function-local control flow transfer |
| 485 // (break/continue/return). The site of the, e.g., break removes the | 920 // (break/continue/return). The site of the, e.g., break removes the |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 TryFinally try_block(this, &finally_entry); | 964 TryFinally try_block(this, &finally_entry); |
| 530 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); | 965 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); |
| 531 Visit(stmt->try_block()); | 966 Visit(stmt->try_block()); |
| 532 __ PopTryHandler(); | 967 __ PopTryHandler(); |
| 533 } | 968 } |
| 534 // Execute the finally block on the way out. | 969 // Execute the finally block on the way out. |
| 535 __ Call(&finally_entry); | 970 __ Call(&finally_entry); |
| 536 } | 971 } |
| 537 | 972 |
| 538 | 973 |
| 539 void FastCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 974 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 540 #ifdef ENABLE_DEBUGGER_SUPPORT | 975 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 541 Comment cmnt(masm_, "[ DebuggerStatement"); | 976 Comment cmnt(masm_, "[ DebuggerStatement"); |
| 542 SetStatementPosition(stmt); | 977 SetStatementPosition(stmt); |
| 543 __ CallRuntime(Runtime::kDebugBreak, 0); | 978 __ CallRuntime(Runtime::kDebugBreak, 0); |
| 544 // Ignore the return value. | 979 // Ignore the return value. |
| 545 #endif | 980 #endif |
| 546 } | 981 } |
| 547 | 982 |
| 548 | 983 |
| 549 void FastCodeGenerator::VisitFunctionBoilerplateLiteral( | 984 void FullCodeGenerator::VisitFunctionBoilerplateLiteral( |
| 550 FunctionBoilerplateLiteral* expr) { | 985 FunctionBoilerplateLiteral* expr) { |
| 551 UNREACHABLE(); | 986 UNREACHABLE(); |
| 552 } | 987 } |
| 553 | 988 |
| 554 | 989 |
| 555 void FastCodeGenerator::VisitConditional(Conditional* expr) { | 990 void FullCodeGenerator::VisitConditional(Conditional* expr) { |
| 556 Comment cmnt(masm_, "[ Conditional"); | 991 Comment cmnt(masm_, "[ Conditional"); |
| 557 Label true_case, false_case, done; | 992 Label true_case, false_case, done; |
| 558 VisitForControl(expr->condition(), &true_case, &false_case); | 993 VisitForControl(expr->condition(), &true_case, &false_case); |
| 559 | 994 |
| 560 __ bind(&true_case); | 995 __ bind(&true_case); |
| 561 Visit(expr->then_expression()); | 996 Visit(expr->then_expression()); |
| 562 // If control flow falls through Visit, jump to done. | 997 // If control flow falls through Visit, jump to done. |
| 563 if (context_ == Expression::kEffect || context_ == Expression::kValue) { | 998 if (context_ == Expression::kEffect || context_ == Expression::kValue) { |
| 564 __ jmp(&done); | 999 __ jmp(&done); |
| 565 } | 1000 } |
| 566 | 1001 |
| 567 __ bind(&false_case); | 1002 __ bind(&false_case); |
| 568 Visit(expr->else_expression()); | 1003 Visit(expr->else_expression()); |
| 569 // If control flow falls through Visit, merge it with true case here. | 1004 // If control flow falls through Visit, merge it with true case here. |
| 570 if (context_ == Expression::kEffect || context_ == Expression::kValue) { | 1005 if (context_ == Expression::kEffect || context_ == Expression::kValue) { |
| 571 __ bind(&done); | 1006 __ bind(&done); |
| 572 } | 1007 } |
| 573 } | 1008 } |
| 574 | 1009 |
| 575 | 1010 |
| 576 void FastCodeGenerator::VisitSlot(Slot* expr) { | 1011 void FullCodeGenerator::VisitSlot(Slot* expr) { |
| 577 // Slots do not appear directly in the AST. | 1012 // Slots do not appear directly in the AST. |
| 578 UNREACHABLE(); | 1013 UNREACHABLE(); |
| 579 } | 1014 } |
| 580 | 1015 |
| 581 | 1016 |
| 582 void FastCodeGenerator::VisitLiteral(Literal* expr) { | 1017 void FullCodeGenerator::VisitLiteral(Literal* expr) { |
| 583 Comment cmnt(masm_, "[ Literal"); | 1018 Comment cmnt(masm_, "[ Literal"); |
| 584 Apply(context_, expr); | 1019 Apply(context_, expr); |
| 585 } | 1020 } |
| 586 | 1021 |
| 587 | 1022 |
| 588 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 1023 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
| 589 Comment cmnt(masm_, "[ Assignment"); | 1024 Comment cmnt(masm_, "[ Assignment"); |
| 590 // Left-hand side can only be a property, a global or a (parameter or local) | 1025 // Left-hand side can only be a property, a global or a (parameter or local) |
| 591 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1026 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 592 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1027 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 593 LhsKind assign_type = VARIABLE; | 1028 LhsKind assign_type = VARIABLE; |
| 594 Property* prop = expr->target()->AsProperty(); | 1029 Property* prop = expr->target()->AsProperty(); |
| 595 if (prop != NULL) { | 1030 if (prop != NULL) { |
| 596 assign_type = | 1031 assign_type = |
| 597 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 1032 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
| 598 } | 1033 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 case NAMED_PROPERTY: | 1092 case NAMED_PROPERTY: |
| 658 EmitNamedPropertyAssignment(expr); | 1093 EmitNamedPropertyAssignment(expr); |
| 659 break; | 1094 break; |
| 660 case KEYED_PROPERTY: | 1095 case KEYED_PROPERTY: |
| 661 EmitKeyedPropertyAssignment(expr); | 1096 EmitKeyedPropertyAssignment(expr); |
| 662 break; | 1097 break; |
| 663 } | 1098 } |
| 664 } | 1099 } |
| 665 | 1100 |
| 666 | 1101 |
| 667 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 1102 void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 668 // Call runtime routine to allocate the catch extension object and | 1103 // Call runtime routine to allocate the catch extension object and |
| 669 // assign the exception value to the catch variable. | 1104 // assign the exception value to the catch variable. |
| 670 Comment cmnt(masm_, "[ CatchExtensionObject"); | 1105 Comment cmnt(masm_, "[ CatchExtensionObject"); |
| 671 VisitForValue(expr->key(), kStack); | 1106 VisitForValue(expr->key(), kStack); |
| 672 VisitForValue(expr->value(), kStack); | 1107 VisitForValue(expr->value(), kStack); |
| 673 // Create catch extension object. | 1108 // Create catch extension object. |
| 674 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); | 1109 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); |
| 675 Apply(context_, result_register()); | 1110 Apply(context_, result_register()); |
| 676 } | 1111 } |
| 677 | 1112 |
| 678 | 1113 |
| 679 void FastCodeGenerator::VisitThrow(Throw* expr) { | 1114 void FullCodeGenerator::VisitThrow(Throw* expr) { |
| 680 Comment cmnt(masm_, "[ Throw"); | 1115 Comment cmnt(masm_, "[ Throw"); |
| 681 VisitForValue(expr->exception(), kStack); | 1116 VisitForValue(expr->exception(), kStack); |
| 682 __ CallRuntime(Runtime::kThrow, 1); | 1117 __ CallRuntime(Runtime::kThrow, 1); |
| 683 // Never returns here. | 1118 // Never returns here. |
| 684 } | 1119 } |
| 685 | 1120 |
| 686 | 1121 |
| 687 int FastCodeGenerator::TryFinally::Exit(int stack_depth) { | 1122 int FullCodeGenerator::TryFinally::Exit(int stack_depth) { |
| 688 // The macros used here must preserve the result register. | 1123 // The macros used here must preserve the result register. |
| 689 __ Drop(stack_depth); | 1124 __ Drop(stack_depth); |
| 690 __ PopTryHandler(); | 1125 __ PopTryHandler(); |
| 691 __ Call(finally_entry_); | 1126 __ Call(finally_entry_); |
| 692 return 0; | 1127 return 0; |
| 693 } | 1128 } |
| 694 | 1129 |
| 695 | 1130 |
| 696 int FastCodeGenerator::TryCatch::Exit(int stack_depth) { | 1131 int FullCodeGenerator::TryCatch::Exit(int stack_depth) { |
| 697 // The macros used here must preserve the result register. | 1132 // The macros used here must preserve the result register. |
| 698 __ Drop(stack_depth); | 1133 __ Drop(stack_depth); |
| 699 __ PopTryHandler(); | 1134 __ PopTryHandler(); |
| 700 return 0; | 1135 return 0; |
| 701 } | 1136 } |
| 702 | 1137 |
| 703 | 1138 |
| 704 #undef __ | 1139 #undef __ |
| 705 | 1140 |
| 706 | 1141 |
| 707 } } // namespace v8::internal | 1142 } } // namespace v8::internal |
| OLD | NEW |