| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 return; \ | 44 return; \ |
| 45 } while (false) | 45 } while (false) |
| 46 | 46 |
| 47 | 47 |
| 48 #define CHECK_BAILOUT \ | 48 #define CHECK_BAILOUT \ |
| 49 do { \ | 49 do { \ |
| 50 if (!has_supported_syntax_) return; \ | 50 if (!has_supported_syntax_) return; \ |
| 51 } while (false) | 51 } while (false) |
| 52 | 52 |
| 53 | 53 |
| 54 void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun, | 54 void FastCodeGenSyntaxChecker::Check(CompilationInfo* info) { |
| 55 CompilationInfo* info) { | |
| 56 info_ = info; | 55 info_ = info; |
| 57 | 56 |
| 58 // We do not specialize if we do not have a receiver or if it is not a | 57 // We do not specialize if we do not have a receiver or if it is not a |
| 59 // JS object with fast mode properties. | 58 // JS object with fast mode properties. |
| 60 if (!info->has_receiver()) BAILOUT("No receiver"); | 59 if (!info->has_receiver()) BAILOUT("No receiver"); |
| 61 if (!info->receiver()->IsJSObject()) BAILOUT("Receiver is not an object"); | 60 if (!info->receiver()->IsJSObject()) BAILOUT("Receiver is not an object"); |
| 62 Handle<JSObject> object = Handle<JSObject>::cast(info->receiver()); | 61 Handle<JSObject> object = Handle<JSObject>::cast(info->receiver()); |
| 63 if (!object->HasFastProperties()) BAILOUT("Receiver is in dictionary mode"); | 62 if (!object->HasFastProperties()) BAILOUT("Receiver is in dictionary mode"); |
| 64 | 63 |
| 65 // We do not support stack or heap slots (both of which require | 64 // We do not support stack or heap slots (both of which require |
| 66 // allocation). | 65 // allocation). |
| 67 Scope* scope = fun->scope(); | 66 Scope* scope = info->scope(); |
| 68 if (scope->num_stack_slots() > 0) { | 67 if (scope->num_stack_slots() > 0) { |
| 69 BAILOUT("Function has stack-allocated locals"); | 68 BAILOUT("Function has stack-allocated locals"); |
| 70 } | 69 } |
| 71 if (scope->num_heap_slots() > 0) { | 70 if (scope->num_heap_slots() > 0) { |
| 72 BAILOUT("Function has context-allocated locals"); | 71 BAILOUT("Function has context-allocated locals"); |
| 73 } | 72 } |
| 74 | 73 |
| 75 VisitDeclarations(scope->declarations()); | 74 VisitDeclarations(scope->declarations()); |
| 76 CHECK_BAILOUT; | 75 CHECK_BAILOUT; |
| 77 | 76 |
| 78 // We do not support empty function bodies. | 77 // We do not support empty function bodies. |
| 79 if (fun->body()->is_empty()) BAILOUT("Function has an empty body"); | 78 if (info->function()->body()->is_empty()) { |
| 80 VisitStatements(fun->body()); | 79 BAILOUT("Function has an empty body"); |
| 80 } |
| 81 VisitStatements(info->function()->body()); |
| 81 } | 82 } |
| 82 | 83 |
| 83 | 84 |
| 84 void FastCodeGenSyntaxChecker::VisitDeclarations( | 85 void FastCodeGenSyntaxChecker::VisitDeclarations( |
| 85 ZoneList<Declaration*>* decls) { | 86 ZoneList<Declaration*>* decls) { |
| 86 if (!decls->is_empty()) BAILOUT("Function has declarations"); | 87 if (!decls->is_empty()) BAILOUT("Function has declarations"); |
| 87 } | 88 } |
| 88 | 89 |
| 89 | 90 |
| 90 void FastCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) { | 91 void FastCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 | 207 |
| 207 | 208 |
| 208 void FastCodeGenSyntaxChecker::VisitSlot(Slot* expr) { | 209 void FastCodeGenSyntaxChecker::VisitSlot(Slot* expr) { |
| 209 UNREACHABLE(); | 210 UNREACHABLE(); |
| 210 } | 211 } |
| 211 | 212 |
| 212 | 213 |
| 213 void FastCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) { | 214 void FastCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) { |
| 214 // Only global variable references are supported. | 215 // Only global variable references are supported. |
| 215 Variable* var = expr->var(); | 216 Variable* var = expr->var(); |
| 216 if (!var->is_global()) BAILOUT("Non-global variable"); | 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.IsValid() || !lookup.IsDontDelete()) { |
| 224 BAILOUT("Non-existing or deletable global variable"); |
| 225 } |
| 226 } |
| 217 } | 227 } |
| 218 | 228 |
| 219 | 229 |
| 220 void FastCodeGenSyntaxChecker::VisitLiteral(Literal* expr) { | 230 void FastCodeGenSyntaxChecker::VisitLiteral(Literal* expr) { |
| 221 BAILOUT("Literal"); | 231 BAILOUT("Literal"); |
| 222 } | 232 } |
| 223 | 233 |
| 224 | 234 |
| 225 void FastCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) { | 235 void FastCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 226 BAILOUT("RegExpLiteral"); | 236 BAILOUT("RegExpLiteral"); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { | 335 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { |
| 326 BAILOUT("ThisFunction"); | 336 BAILOUT("ThisFunction"); |
| 327 } | 337 } |
| 328 | 338 |
| 329 #undef BAILOUT | 339 #undef BAILOUT |
| 330 #undef CHECK_BAILOUT | 340 #undef CHECK_BAILOUT |
| 331 | 341 |
| 332 | 342 |
| 333 #define __ ACCESS_MASM(masm()) | 343 #define __ ACCESS_MASM(masm()) |
| 334 | 344 |
| 335 Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun, | 345 Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) { |
| 336 Handle<Script> script, | |
| 337 bool is_eval, | |
| 338 CompilationInfo* info) { | |
| 339 // Label the AST before calling MakeCodePrologue, so AST node numbers are | 346 // Label the AST before calling MakeCodePrologue, so AST node numbers are |
| 340 // printed with the AST. | 347 // printed with the AST. |
| 341 AstLabeler labeler; | 348 AstLabeler labeler; |
| 342 labeler.Label(fun); | 349 labeler.Label(info); |
| 343 info->set_has_this_properties(labeler.has_this_properties()); | |
| 344 | 350 |
| 345 CodeGenerator::MakeCodePrologue(fun); | 351 CodeGenerator::MakeCodePrologue(info); |
| 346 | 352 |
| 347 const int kInitialBufferSize = 4 * KB; | 353 const int kInitialBufferSize = 4 * KB; |
| 348 MacroAssembler masm(NULL, kInitialBufferSize); | 354 MacroAssembler masm(NULL, kInitialBufferSize); |
| 349 | 355 |
| 350 // Generate the fast-path code. | 356 // Generate the fast-path code. |
| 351 FastCodeGenerator fast_cgen(&masm, script, is_eval); | 357 FastCodeGenerator fast_cgen(&masm); |
| 352 fast_cgen.Generate(fun, info); | 358 fast_cgen.Generate(info); |
| 353 if (fast_cgen.HasStackOverflow()) { | 359 if (fast_cgen.HasStackOverflow()) { |
| 354 ASSERT(!Top::has_pending_exception()); | 360 ASSERT(!Top::has_pending_exception()); |
| 355 return Handle<Code>::null(); | 361 return Handle<Code>::null(); |
| 356 } | 362 } |
| 357 | 363 |
| 358 // Generate the full code for the function in bailout mode, using the same | 364 // Generate the full code for the function in bailout mode, using the same |
| 359 // macro assembler. | 365 // macro assembler. |
| 360 CodeGenerator cgen(&masm, script, is_eval); | 366 CodeGenerator cgen(&masm); |
| 361 CodeGeneratorScope scope(&cgen); | 367 CodeGeneratorScope scope(&cgen); |
| 362 cgen.Generate(fun, CodeGenerator::SECONDARY, info); | 368 cgen.Generate(info, CodeGenerator::SECONDARY); |
| 363 if (cgen.HasStackOverflow()) { | 369 if (cgen.HasStackOverflow()) { |
| 364 ASSERT(!Top::has_pending_exception()); | 370 ASSERT(!Top::has_pending_exception()); |
| 365 return Handle<Code>::null(); | 371 return Handle<Code>::null(); |
| 366 } | 372 } |
| 367 | 373 |
| 368 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); | 374 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); |
| 369 return CodeGenerator::MakeCodeEpilogue(fun, &masm, flags, script); | 375 return CodeGenerator::MakeCodeEpilogue(&masm, flags, info); |
| 370 } | 376 } |
| 371 | 377 |
| 372 | 378 |
| 373 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { | 379 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { |
| 374 UNREACHABLE(); | 380 UNREACHABLE(); |
| 375 } | 381 } |
| 376 | 382 |
| 377 | 383 |
| 378 void FastCodeGenerator::VisitBlock(Block* stmt) { | 384 void FastCodeGenerator::VisitBlock(Block* stmt) { |
| 379 VisitStatements(stmt->statements()); | 385 VisitStatements(stmt->statements()); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 } | 487 } |
| 482 | 488 |
| 483 | 489 |
| 484 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 490 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 485 ASSERT(expr->var()->is_global() && !expr->var()->is_this()); | 491 ASSERT(expr->var()->is_global() && !expr->var()->is_this()); |
| 486 Comment cmnt(masm(), ";; Global"); | 492 Comment cmnt(masm(), ";; Global"); |
| 487 if (FLAG_print_ir) { | 493 if (FLAG_print_ir) { |
| 488 SmartPointer<char> name = expr->name()->ToCString(); | 494 SmartPointer<char> name = expr->name()->ToCString(); |
| 489 PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); | 495 PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); |
| 490 } | 496 } |
| 491 EmitGlobalVariableLoad(expr->name()); | 497 |
| 498 // Check if we can compile a global variable load directly from the cell. |
| 499 ASSERT(info()->has_global_object()); |
| 500 LookupResult lookup; |
| 501 info()->global_object()->Lookup(*expr->name(), &lookup); |
| 502 // We only support DontDelete properties for now. |
| 503 ASSERT(lookup.IsValid()); |
| 504 ASSERT(lookup.IsDontDelete()); |
| 505 Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup)); |
| 506 EmitGlobalVariableLoad(cell); |
| 492 } | 507 } |
| 493 | 508 |
| 494 | 509 |
| 495 void FastCodeGenerator::VisitLiteral(Literal* expr) { | 510 void FastCodeGenerator::VisitLiteral(Literal* expr) { |
| 496 UNREACHABLE(); | 511 UNREACHABLE(); |
| 497 } | 512 } |
| 498 | 513 |
| 499 | 514 |
| 500 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 515 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 501 UNREACHABLE(); | 516 UNREACHABLE(); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 | 601 |
| 587 | 602 |
| 588 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 603 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 589 UNREACHABLE(); | 604 UNREACHABLE(); |
| 590 } | 605 } |
| 591 | 606 |
| 592 #undef __ | 607 #undef __ |
| 593 | 608 |
| 594 | 609 |
| 595 } } // namespace v8::internal | 610 } } // namespace v8::internal |
| OLD | NEW |