| 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 20 matching lines...) Expand all Loading... |
| 31 #include "compiler.h" | 31 #include "compiler.h" |
| 32 #include "full-codegen.h" | 32 #include "full-codegen.h" |
| 33 #include "scopes.h" | 33 #include "scopes.h" |
| 34 #include "stub-cache.h" | 34 #include "stub-cache.h" |
| 35 #include "debug.h" | 35 #include "debug.h" |
| 36 #include "liveedit.h" | 36 #include "liveedit.h" |
| 37 | 37 |
| 38 namespace v8 { | 38 namespace v8 { |
| 39 namespace internal { | 39 namespace internal { |
| 40 | 40 |
| 41 #define BAILOUT(reason) \ | |
| 42 do { \ | |
| 43 if (FLAG_trace_bailout) { \ | |
| 44 PrintF("%s\n", reason); \ | |
| 45 } \ | |
| 46 has_supported_syntax_ = false; \ | |
| 47 return; \ | |
| 48 } while (false) | |
| 49 | |
| 50 | |
| 51 #define CHECK_BAILOUT \ | |
| 52 do { \ | |
| 53 if (!has_supported_syntax_) return; \ | |
| 54 } while (false) | |
| 55 | |
| 56 | |
| 57 void FullCodeGenSyntaxChecker::Check(FunctionLiteral* fun) { | |
| 58 Scope* scope = fun->scope(); | |
| 59 VisitDeclarations(scope->declarations()); | |
| 60 CHECK_BAILOUT; | |
| 61 | |
| 62 VisitStatements(fun->body()); | |
| 63 } | |
| 64 | |
| 65 | |
| 66 void FullCodeGenSyntaxChecker::VisitDeclarations( | |
| 67 ZoneList<Declaration*>* decls) { | |
| 68 for (int i = 0; i < decls->length(); i++) { | |
| 69 Visit(decls->at(i)); | |
| 70 CHECK_BAILOUT; | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 | |
| 75 void FullCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) { | |
| 76 for (int i = 0, len = stmts->length(); i < len; i++) { | |
| 77 Visit(stmts->at(i)); | |
| 78 CHECK_BAILOUT; | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 | |
| 83 void FullCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) { | |
| 84 Property* prop = decl->proxy()->AsProperty(); | |
| 85 if (prop != NULL) { | |
| 86 Visit(prop->obj()); | |
| 87 Visit(prop->key()); | |
| 88 } | |
| 89 | |
| 90 if (decl->fun() != NULL) { | |
| 91 Visit(decl->fun()); | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 | |
| 96 void FullCodeGenSyntaxChecker::VisitBlock(Block* stmt) { | |
| 97 VisitStatements(stmt->statements()); | |
| 98 } | |
| 99 | |
| 100 | |
| 101 void FullCodeGenSyntaxChecker::VisitExpressionStatement( | |
| 102 ExpressionStatement* stmt) { | |
| 103 Visit(stmt->expression()); | |
| 104 } | |
| 105 | |
| 106 | |
| 107 void FullCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) { | |
| 108 // Supported. | |
| 109 } | |
| 110 | |
| 111 | |
| 112 void FullCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) { | |
| 113 Visit(stmt->condition()); | |
| 114 CHECK_BAILOUT; | |
| 115 Visit(stmt->then_statement()); | |
| 116 CHECK_BAILOUT; | |
| 117 Visit(stmt->else_statement()); | |
| 118 } | |
| 119 | |
| 120 | |
| 121 void FullCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) { | |
| 122 // Supported. | |
| 123 } | |
| 124 | |
| 125 | |
| 126 void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) { | |
| 127 // Supported. | |
| 128 } | |
| 129 | |
| 130 | |
| 131 void FullCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) { | |
| 132 Visit(stmt->expression()); | |
| 133 } | |
| 134 | |
| 135 | |
| 136 void FullCodeGenSyntaxChecker::VisitWithEnterStatement( | |
| 137 WithEnterStatement* stmt) { | |
| 138 Visit(stmt->expression()); | |
| 139 } | |
| 140 | |
| 141 | |
| 142 void FullCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) { | |
| 143 // Supported. | |
| 144 } | |
| 145 | |
| 146 | |
| 147 void FullCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) { | |
| 148 BAILOUT("SwitchStatement"); | |
| 149 } | |
| 150 | |
| 151 | |
| 152 void FullCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) { | |
| 153 Visit(stmt->cond()); | |
| 154 CHECK_BAILOUT; | |
| 155 Visit(stmt->body()); | |
| 156 } | |
| 157 | |
| 158 | |
| 159 void FullCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) { | |
| 160 Visit(stmt->cond()); | |
| 161 CHECK_BAILOUT; | |
| 162 Visit(stmt->body()); | |
| 163 } | |
| 164 | |
| 165 | |
| 166 void FullCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) { | |
| 167 if (!FLAG_always_full_compiler) BAILOUT("ForStatement"); | |
| 168 if (stmt->init() != NULL) { | |
| 169 Visit(stmt->init()); | |
| 170 CHECK_BAILOUT; | |
| 171 } | |
| 172 if (stmt->cond() != NULL) { | |
| 173 Visit(stmt->cond()); | |
| 174 CHECK_BAILOUT; | |
| 175 } | |
| 176 Visit(stmt->body()); | |
| 177 if (stmt->next() != NULL) { | |
| 178 CHECK_BAILOUT; | |
| 179 Visit(stmt->next()); | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 | |
| 184 void FullCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) { | |
| 185 BAILOUT("ForInStatement"); | |
| 186 } | |
| 187 | |
| 188 | |
| 189 void FullCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) { | |
| 190 Visit(stmt->try_block()); | |
| 191 CHECK_BAILOUT; | |
| 192 Visit(stmt->catch_block()); | |
| 193 } | |
| 194 | |
| 195 | |
| 196 void FullCodeGenSyntaxChecker::VisitTryFinallyStatement( | |
| 197 TryFinallyStatement* stmt) { | |
| 198 Visit(stmt->try_block()); | |
| 199 CHECK_BAILOUT; | |
| 200 Visit(stmt->finally_block()); | |
| 201 } | |
| 202 | |
| 203 | |
| 204 void FullCodeGenSyntaxChecker::VisitDebuggerStatement( | |
| 205 DebuggerStatement* stmt) { | |
| 206 // Supported. | |
| 207 } | |
| 208 | |
| 209 | |
| 210 void FullCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) { | |
| 211 // Supported. | |
| 212 } | |
| 213 | |
| 214 | |
| 215 void FullCodeGenSyntaxChecker::VisitSharedFunctionInfoLiteral( | |
| 216 SharedFunctionInfoLiteral* expr) { | |
| 217 BAILOUT("SharedFunctionInfoLiteral"); | |
| 218 } | |
| 219 | |
| 220 | |
| 221 void FullCodeGenSyntaxChecker::VisitConditional(Conditional* expr) { | |
| 222 Visit(expr->condition()); | |
| 223 CHECK_BAILOUT; | |
| 224 Visit(expr->then_expression()); | |
| 225 CHECK_BAILOUT; | |
| 226 Visit(expr->else_expression()); | |
| 227 } | |
| 228 | |
| 229 | |
| 230 void FullCodeGenSyntaxChecker::VisitSlot(Slot* expr) { | |
| 231 UNREACHABLE(); | |
| 232 } | |
| 233 | |
| 234 | |
| 235 void FullCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) { | |
| 236 // Supported. | |
| 237 } | |
| 238 | |
| 239 | |
| 240 void FullCodeGenSyntaxChecker::VisitLiteral(Literal* expr) { | |
| 241 // Supported. | |
| 242 } | |
| 243 | |
| 244 | |
| 245 void FullCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) { | |
| 246 // Supported. | |
| 247 } | |
| 248 | |
| 249 | |
| 250 void FullCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) { | |
| 251 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); | |
| 252 | |
| 253 for (int i = 0, len = properties->length(); i < len; i++) { | |
| 254 ObjectLiteral::Property* property = properties->at(i); | |
| 255 if (property->IsCompileTimeValue()) continue; | |
| 256 Visit(property->key()); | |
| 257 CHECK_BAILOUT; | |
| 258 Visit(property->value()); | |
| 259 CHECK_BAILOUT; | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 | |
| 264 void FullCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) { | |
| 265 ZoneList<Expression*>* subexprs = expr->values(); | |
| 266 for (int i = 0, len = subexprs->length(); i < len; i++) { | |
| 267 Expression* subexpr = subexprs->at(i); | |
| 268 if (subexpr->AsLiteral() != NULL) continue; | |
| 269 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | |
| 270 Visit(subexpr); | |
| 271 CHECK_BAILOUT; | |
| 272 } | |
| 273 } | |
| 274 | |
| 275 | |
| 276 void FullCodeGenSyntaxChecker::VisitCatchExtensionObject( | |
| 277 CatchExtensionObject* expr) { | |
| 278 Visit(expr->key()); | |
| 279 CHECK_BAILOUT; | |
| 280 Visit(expr->value()); | |
| 281 } | |
| 282 | |
| 283 | |
| 284 void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) { | |
| 285 Token::Value op = expr->op(); | |
| 286 if (op == Token::INIT_CONST) BAILOUT("initialize constant"); | |
| 287 | |
| 288 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | |
| 289 Property* prop = expr->target()->AsProperty(); | |
| 290 ASSERT(var == NULL || prop == NULL); | |
| 291 if (var != NULL) { | |
| 292 if (var->mode() == Variable::CONST) BAILOUT("Assignment to const"); | |
| 293 // All other variables are supported. | |
| 294 } else if (prop != NULL) { | |
| 295 Visit(prop->obj()); | |
| 296 CHECK_BAILOUT; | |
| 297 Visit(prop->key()); | |
| 298 CHECK_BAILOUT; | |
| 299 } else { | |
| 300 // This is a throw reference error. | |
| 301 BAILOUT("non-variable/non-property assignment"); | |
| 302 } | |
| 303 | |
| 304 Visit(expr->value()); | |
| 305 } | |
| 306 | |
| 307 | |
| 308 void FullCodeGenSyntaxChecker::VisitThrow(Throw* expr) { | |
| 309 Visit(expr->exception()); | |
| 310 } | |
| 311 | |
| 312 | |
| 313 void FullCodeGenSyntaxChecker::VisitProperty(Property* expr) { | |
| 314 Visit(expr->obj()); | |
| 315 CHECK_BAILOUT; | |
| 316 Visit(expr->key()); | |
| 317 } | |
| 318 | |
| 319 | |
| 320 void FullCodeGenSyntaxChecker::VisitCall(Call* expr) { | |
| 321 Expression* fun = expr->expression(); | |
| 322 ZoneList<Expression*>* args = expr->arguments(); | |
| 323 Variable* var = fun->AsVariableProxy()->AsVariable(); | |
| 324 | |
| 325 // Check for supported calls | |
| 326 if (var != NULL && var->is_possibly_eval()) { | |
| 327 BAILOUT("call to the identifier 'eval'"); | |
| 328 } else if (var != NULL && !var->is_this() && var->is_global()) { | |
| 329 // Calls to global variables are supported. | |
| 330 } else if (var != NULL && var->slot() != NULL && | |
| 331 var->slot()->type() == Slot::LOOKUP) { | |
| 332 BAILOUT("call to a lookup slot"); | |
| 333 } else if (fun->AsProperty() != NULL) { | |
| 334 Property* prop = fun->AsProperty(); | |
| 335 Visit(prop->obj()); | |
| 336 CHECK_BAILOUT; | |
| 337 Visit(prop->key()); | |
| 338 CHECK_BAILOUT; | |
| 339 } else { | |
| 340 // Otherwise the call is supported if the function expression is. | |
| 341 Visit(fun); | |
| 342 } | |
| 343 // Check all arguments to the call. | |
| 344 for (int i = 0; i < args->length(); i++) { | |
| 345 Visit(args->at(i)); | |
| 346 CHECK_BAILOUT; | |
| 347 } | |
| 348 } | |
| 349 | |
| 350 | |
| 351 void FullCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { | |
| 352 Visit(expr->expression()); | |
| 353 CHECK_BAILOUT; | |
| 354 ZoneList<Expression*>* args = expr->arguments(); | |
| 355 // Check all arguments to the call | |
| 356 for (int i = 0; i < args->length(); i++) { | |
| 357 Visit(args->at(i)); | |
| 358 CHECK_BAILOUT; | |
| 359 } | |
| 360 } | |
| 361 | |
| 362 | |
| 363 void FullCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { | |
| 364 // Check for inline runtime call | |
| 365 if (expr->name()->Get(0) == '_' && | |
| 366 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { | |
| 367 BAILOUT("inlined runtime call"); | |
| 368 } | |
| 369 // Check all arguments to the call. (Relies on TEMP meaning STACK.) | |
| 370 for (int i = 0; i < expr->arguments()->length(); i++) { | |
| 371 Visit(expr->arguments()->at(i)); | |
| 372 CHECK_BAILOUT; | |
| 373 } | |
| 374 } | |
| 375 | |
| 376 | |
| 377 void FullCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { | |
| 378 switch (expr->op()) { | |
| 379 case Token::ADD: | |
| 380 case Token::BIT_NOT: | |
| 381 case Token::NOT: | |
| 382 case Token::SUB: | |
| 383 case Token::TYPEOF: | |
| 384 case Token::VOID: | |
| 385 Visit(expr->expression()); | |
| 386 break; | |
| 387 case Token::DELETE: | |
| 388 BAILOUT("UnaryOperation: DELETE"); | |
| 389 default: | |
| 390 UNREACHABLE(); | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 | |
| 395 void FullCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { | |
| 396 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | |
| 397 Property* prop = expr->expression()->AsProperty(); | |
| 398 ASSERT(var == NULL || prop == NULL); | |
| 399 if (var != NULL) { | |
| 400 // All global variables are supported. | |
| 401 if (!var->is_global()) { | |
| 402 ASSERT(var->slot() != NULL); | |
| 403 Slot::Type type = var->slot()->type(); | |
| 404 if (type == Slot::LOOKUP) { | |
| 405 BAILOUT("CountOperation with lookup slot"); | |
| 406 } | |
| 407 } | |
| 408 } else if (prop != NULL) { | |
| 409 Visit(prop->obj()); | |
| 410 CHECK_BAILOUT; | |
| 411 Visit(prop->key()); | |
| 412 CHECK_BAILOUT; | |
| 413 } else { | |
| 414 // This is a throw reference error. | |
| 415 BAILOUT("CountOperation non-variable/non-property expression"); | |
| 416 } | |
| 417 } | |
| 418 | |
| 419 | |
| 420 void FullCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { | |
| 421 Visit(expr->left()); | |
| 422 CHECK_BAILOUT; | |
| 423 Visit(expr->right()); | |
| 424 } | |
| 425 | |
| 426 | |
| 427 void FullCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { | |
| 428 Visit(expr->left()); | |
| 429 CHECK_BAILOUT; | |
| 430 Visit(expr->right()); | |
| 431 } | |
| 432 | |
| 433 | |
| 434 void FullCodeGenSyntaxChecker::VisitCompareToNull(CompareToNull* expr) { | |
| 435 Visit(expr->expression()); | |
| 436 } | |
| 437 | |
| 438 | |
| 439 void FullCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { | |
| 440 // Supported. | |
| 441 } | |
| 442 | |
| 443 #undef BAILOUT | |
| 444 #undef CHECK_BAILOUT | |
| 445 | |
| 446 | |
| 447 void BreakableStatementChecker::Check(Statement* stmt) { | 41 void BreakableStatementChecker::Check(Statement* stmt) { |
| 448 Visit(stmt); | 42 Visit(stmt); |
| 449 } | 43 } |
| 450 | 44 |
| 451 | 45 |
| 452 void BreakableStatementChecker::Check(Expression* expr) { | 46 void BreakableStatementChecker::Check(Expression* expr) { |
| 453 Visit(expr); | 47 Visit(expr); |
| 454 } | 48 } |
| 455 | 49 |
| 456 | 50 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 | 455 |
| 862 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { | 456 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { |
| 863 Handle<String> name = expr->name(); | 457 Handle<String> name = expr->name(); |
| 864 SmartPointer<char> cstring = name->ToCString(); | 458 SmartPointer<char> cstring = name->ToCString(); |
| 865 | 459 |
| 866 #define CHECK_EMIT_INLINE_CALL(name, x, y) \ | 460 #define CHECK_EMIT_INLINE_CALL(name, x, y) \ |
| 867 if (strcmp("_"#name, *cstring) == 0) { \ | 461 if (strcmp("_"#name, *cstring) == 0) { \ |
| 868 Emit##name(expr->arguments()); \ | 462 Emit##name(expr->arguments()); \ |
| 869 return; \ | 463 return; \ |
| 870 } | 464 } |
| 871 | |
| 872 INLINE_RUNTIME_FUNCTION_LIST(CHECK_EMIT_INLINE_CALL) | 465 INLINE_RUNTIME_FUNCTION_LIST(CHECK_EMIT_INLINE_CALL) |
| 466 #undef CHECK_EMIT_INLINE_CALL |
| 873 UNREACHABLE(); | 467 UNREACHABLE(); |
| 874 #undef CHECK_EMIT_INLINE_CALL | |
| 875 } | 468 } |
| 876 | 469 |
| 877 | 470 |
| 878 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 471 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 879 Comment cmnt(masm_, "[ BinaryOperation"); | 472 Comment cmnt(masm_, "[ BinaryOperation"); |
| 880 switch (expr->op()) { | 473 switch (expr->op()) { |
| 881 case Token::COMMA: | 474 case Token::COMMA: |
| 882 VisitForEffect(expr->left()); | 475 VisitForEffect(expr->left()); |
| 883 Visit(expr->right()); | 476 Visit(expr->right()); |
| 884 break; | 477 break; |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1442 ASSERT(args->length() == 1); | 1035 ASSERT(args->length() == 1); |
| 1443 VisitForValue(args->at(0), kStack); | 1036 VisitForValue(args->at(0), kStack); |
| 1444 __ CallRuntime(Runtime::kRegExpCloneResult, 1); | 1037 __ CallRuntime(Runtime::kRegExpCloneResult, 1); |
| 1445 Apply(context_, result_register()); | 1038 Apply(context_, result_register()); |
| 1446 } | 1039 } |
| 1447 | 1040 |
| 1448 #undef __ | 1041 #undef __ |
| 1449 | 1042 |
| 1450 | 1043 |
| 1451 } } // namespace v8::internal | 1044 } } // namespace v8::internal |
| OLD | NEW |