Changeset 127698 in webkit
- Timestamp:
- Sep 5, 2012 11:17:59 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r127697 r127698 1 2012-09-03 Geoffrey Garen <ggaren@apple.com> 2 3 Named functions should not allocate scope objects for their names 4 https://bugs.webkit.org/show_bug.cgi?id=95659 5 6 Reviewed by Oliver Hunt. 7 8 Added coverage for some extra-tricky cases. 9 10 * fast/js/named-function-expression-expected.txt: 11 * fast/js/script-tests/named-function-expression.js: 12 (shouldBeTrueWithDescription): I rolled my own shouldBeTrue() here to avoid the 13 built-in shouldBe()'s eval scoping, which can change the variable 14 resolution rules I'm trying to test. 15 16 * inspector/debugger/debugger-expand-scope-expected.txt: Not sure why this 17 result used to miss the function name scope, but the new result is a 18 progression, so I've updated the expected results. 19 1 20 2012-09-05 Csaba Osztrogonác <ossy@webkit.org> 2 21 -
trunk/LayoutTests/fast/js/named-function-expression-expected.txt
r75408 r127698 1 Bug 4698 - kjs does not allow named functions infunction expressions.1 Tests variable resolution rules for named function expressions. 2 2 3 3 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". … … 18 18 regression test where kjs regarded an anonymous function declaration (which is illegal) as a FunctionExpr 19 19 PASS var hadError = 0; try { eval("function(){ return 2; };"); } catch(e) { hadError = 1; }; hadError; is 1 20 21 ----- 22 23 PASS: (function closure() { return closure == arguments.callee && !this.closure; })() should be true and is. 24 PASS: (function closure() { closure = 1; return closure == arguments.callee && !this.closure; })() should be true and is. 25 PASS: (function closure(closure) { return closure == 1 && !this.closure; })(1) should be true and is. 26 PASS: (function closure() { var closure = 1; return closure == 1 && !this.closure; })() should be true and is. 27 PASS: (function closure() { function closure() { }; return closure != arguments.callee && !this.closure; })() should be true and is. 28 PASS: (function closure() { return (function() { return closure && !this.closure; })(); })() should be true and is. 29 PASS: (function closure() { return (function() { closure = null; return closure && !this.closure; })(); })() should be true and is. 30 PASS: (function closure() { return (function() { return closure && !this.closure; }); })()() should be true and is. 31 PASS: (function closure() { return (function() { closure = null; return closure && !this.closure; }); })()() should be true and is. 32 PASS: (function closure() { eval("var closure"); return closure == undefined && !this.closure; })() should be true and is. 33 PASS: (function closure() { eval("function closure() { }"); return closure != arguments.callee && !this.closure; })() should be true and is. 34 PASS: (function closure() { eval("var closure;"); closure = 1; return closure == 1 && !this.closure; })() should be true and is. 35 PASS: (function closure() { eval("var closure"); delete closure; return closure == arguments.callee && !this.closure; })() should be true and is. 36 PASS: (function closure() { eval("function closure() { }"); delete closure; return closure == arguments.callee && !this.closure; })() should be true and is. 37 PASS: (function closure() { eval("closure = 1;"); return closure == arguments.callee && !this.closure; })() should be true and is. 20 38 PASS successfullyParsed is true 21 39 -
trunk/LayoutTests/fast/js/script-tests/named-function-expression.js
r98407 r127698 1 1 description( 2 " Bug 4698 - kjs does not allow named functions infunction expressions."2 "Tests variable resolution rules for named function expressions." 3 3 ); 4 4 … … 25 25 debug("regression test where kjs regarded an anonymous function declaration (which is illegal) as a FunctionExpr"); 26 26 shouldBe('var hadError = 0; try { eval("function(){ return 2; };"); } catch(e) { hadError = 1; }; hadError;', "1"); 27 28 debug("\n-----\n"); 29 30 function shouldBeTrueWithDescription(x, xDescription) 31 { 32 if (x) { 33 debug("PASS: " + xDescription + " should be true and is."); 34 return; 35 } 36 37 debug("FAIL: " + xDescription + " should be true but isn't."); 38 } 39 40 // Recursion. 41 shouldBeTrueWithDescription( 42 (function closure() { return closure == arguments.callee && !this.closure; })(), 43 "(function closure() { return closure == arguments.callee && !this.closure; })()" 44 ); 45 46 // Assignment. 47 shouldBeTrueWithDescription( 48 (function closure() { closure = 1; return closure == arguments.callee && !this.closure; })(), 49 "(function closure() { closure = 1; return closure == arguments.callee && !this.closure; })()" 50 ); 51 52 // Function name vs parameter. 53 shouldBeTrueWithDescription( 54 (function closure(closure) { return closure == 1 && !this.closure; })(1), 55 "(function closure(closure) { return closure == 1 && !this.closure; })(1)" 56 ); 57 58 // Function name vs var. 59 shouldBeTrueWithDescription( 60 (function closure() { var closure = 1; return closure == 1 && !this.closure; })(), 61 "(function closure() { var closure = 1; return closure == 1 && !this.closure; })()" 62 ); 63 64 // Function name vs declared function. 65 shouldBeTrueWithDescription( 66 (function closure() { function closure() { }; return closure != arguments.callee && !this.closure; })(), 67 "(function closure() { function closure() { }; return closure != arguments.callee && !this.closure; })()" 68 ); 69 70 // Resolve before tear-off. 71 shouldBeTrueWithDescription( 72 (function closure() { return (function() { return closure && !this.closure; })(); })(), 73 "(function closure() { return (function() { return closure && !this.closure; })(); })()" 74 ); 75 76 // Resolve assignment before tear-off. 77 shouldBeTrueWithDescription( 78 (function closure() { return (function() { closure = null; return closure && !this.closure; })(); })(), 79 "(function closure() { return (function() { closure = null; return closure && !this.closure; })(); })()" 80 ); 81 82 // Resolve after tear-off. 83 shouldBeTrueWithDescription( 84 (function closure() { return (function() { return closure && !this.closure; }); })()(), 85 "(function closure() { return (function() { return closure && !this.closure; }); })()()" 86 ); 87 88 // Resolve assignment after tear-off. 89 shouldBeTrueWithDescription( 90 (function closure() { return (function() { closure = null; return closure && !this.closure; }); })()(), 91 "(function closure() { return (function() { closure = null; return closure && !this.closure; }); })()()" 92 ); 93 94 // Eval var shadowing (should overwrite). 95 shouldBeTrueWithDescription( 96 (function closure() { eval("var closure"); return closure == undefined && !this.closure; })(), 97 "(function closure() { eval(\"var closure\"); return closure == undefined && !this.closure; })()" 98 ); 99 100 // Eval function shadowing (should overwrite). 101 shouldBeTrueWithDescription( 102 (function closure() { eval("function closure() { }"); return closure != arguments.callee && !this.closure; })(), 103 "(function closure() { eval(\"function closure() { }\"); return closure != arguments.callee && !this.closure; })()" 104 ); 105 106 // Eval shadowing (should overwrite), followed by put (should overwrite). 107 shouldBeTrueWithDescription( 108 (function closure() { eval("var closure;"); closure = 1; return closure == 1 && !this.closure; })(), 109 "(function closure() { eval(\"var closure;\"); closure = 1; return closure == 1 && !this.closure; })()" 110 ); 111 112 // Eval var shadowing, followed by delete (should not overwrite). 113 shouldBeTrueWithDescription( 114 (function closure() { eval("var closure"); delete closure; return closure == arguments.callee && !this.closure; })(), 115 "(function closure() { eval(\"var closure\"); delete closure; return closure == arguments.callee && !this.closure; })()" 116 ); 117 118 // Eval function shadowing, followed by delete (should not overwrite). 119 shouldBeTrueWithDescription( 120 (function closure() { eval("function closure() { }"); delete closure; return closure == arguments.callee && !this.closure; })(), 121 "(function closure() { eval(\"function closure() { }\"); delete closure; return closure == arguments.callee && !this.closure; })()" 122 ); 123 124 // Eval assignment (should not overwrite). 125 shouldBeTrueWithDescription( 126 (function closure() { eval("closure = 1;"); return closure == arguments.callee && !this.closure; })(), 127 "(function closure() { eval(\"closure = 1;\"); return closure == arguments.callee && !this.closure; })()" 128 ); -
trunk/LayoutTests/inspector/debugger/debugger-expand-scope-expected.txt
r118161 r127698 20 20 makeClosureLocalVar: "local.TextParam" 21 21 n: "TextParam" 22 WindowWith Block 23 makeClosure: function makeClosure(n) { 22 24 WindowGlobal 23 25 <section collapsed> -
trunk/Source/JavaScriptCore/ChangeLog
r127676 r127698 1 2012-09-05 Geoffrey Garen <ggaren@apple.com> 2 3 Named functions should not allocate scope objects for their names 4 https://bugs.webkit.org/show_bug.cgi?id=95659 5 6 Reviewed by Oliver Hunt. 7 8 In most cases, we can merge a function expression's name into its symbol 9 table. This reduces memory footprint per closure from three objects 10 (function + activation + name scope) to two (function + activation), 11 speeds up closure allocation, and speeds up recursive calls. 12 13 In the case of a named function expression that contains a non-strict 14 eval, the rules are so bat-poop crazy that I don't know how to model 15 them without an extra object. Since functions now default to not having 16 such an object, this case needs to allocate the object on function 17 entry. 18 19 Therefore, this patch makes the slow case a bit slower so the fast case 20 can be faster and more memory-efficient. (Note that the slow case already 21 allocates an activation on entry, and until recently also allocated a 22 scope chain node on entry, so adding one allocation on entry shouldn't 23 break the bank.) 24 25 * bytecode/CodeBlock.cpp: 26 (JSC::CodeBlock::CodeBlock): Caught a missed initializer. No behavior change. 27 28 * bytecompiler/BytecodeGenerator.cpp: 29 (JSC::BytecodeGenerator::BytecodeGenerator): Put the callee in static scope 30 during compilation so it doesn't need to be in dynamic scope at runtime. 31 32 (JSC::BytecodeGenerator::resolveCallee): 33 (JSC::BytecodeGenerator::addCallee): Helper functions for either statically 34 resolving the callee or adding a dynamic scope that will resolve to it, 35 depending on whether you're in the fast path. 36 37 We move the callee into a var location if it's captured because activations 38 prefer to have contiguous ranges of captured variables. 39 40 * bytecompiler/BytecodeGenerator.h: 41 (JSC::BytecodeGenerator::registerFor): 42 (BytecodeGenerator): 43 44 * dfg/DFGOperations.cpp: 45 * interpreter/Interpreter.cpp: 46 (JSC::Interpreter::privateExecute): 47 * jit/JITStubs.cpp: 48 (JSC::DEFINE_STUB_FUNCTION): 49 * llint/LLIntSlowPaths.cpp: 50 (JSC::LLInt::LLINT_SLOW_PATH_DECL): This is the point of the patch: remove 51 one allocation in the case of a named function expression. 52 53 * parser/Parser.cpp: 54 (JSC::::Parser): 55 * parser/Parser.h: 56 (JSC::Scope::declareCallee): 57 (Scope): 58 (Parser): 59 (JSC::parse): 60 * runtime/Executable.cpp: 61 (JSC::EvalExecutable::compileInternal): 62 (JSC::ProgramExecutable::checkSyntax): 63 (JSC::ProgramExecutable::compileInternal): 64 (JSC::FunctionExecutable::produceCodeBlockFor): 65 (JSC::FunctionExecutable::fromGlobalCode): Pipe the callee's name through 66 the parser so we get accurate information on whether the callee was captured. 67 68 (JSC::FunctionExecutable::FunctionExecutable): 69 (JSC::EvalExecutable::compileInternal): 70 (JSC::ProgramExecutable::checkSyntax): 71 (JSC::ProgramExecutable::compileInternal): 72 (JSC::FunctionExecutable::produceCodeBlockFor): 73 (JSC::FunctionExecutable::fromGlobalCode): 74 * runtime/Executable.h: 75 (JSC::FunctionExecutable::create): 76 (FunctionExecutable): 77 (JSC::FunctionExecutable::finishCreation): I had to refactor function 78 creation to support the following function constructor quirk: the function 79 gets a name, but its name is not in lexical scope. 80 81 To simplify this, FunctionExecutable now automatically extracts all the 82 data it needs from the parsed node. The special "fromGlobalCode" path 83 used by the function constructor creates an anonymous function, and then 84 quirkily sets the value used by the .name property to be non-null, even 85 though the parsed name is null. 86 87 * runtime/JSNameScope.h: 88 (JSC::JSNameScope::create): 89 (JSC::JSNameScope::JSNameScope): Added support for explicitly specifying 90 your container scope. The compiler uses this for named function expressions. 91 1 92 2012-09-05 Gavin Barraclough <barraclough@apple.com> 2 93 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r127505 r127698 1753 1753 , m_numCalleeRegisters(0) 1754 1754 , m_numVars(0) 1755 , m_numCapturedVars(0) 1755 1756 , m_isConstructor(isConstructor) 1756 1757 , m_numParameters(0) -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r127647 r127698 34 34 #include "BatchedTransitionOptimizer.h" 35 35 #include "Comment.h" 36 #include "Interpreter.h" 36 37 #include "JSActivation.h" 37 38 #include "JSFunction.h" 38 #include " Interpreter.h"39 #include "JSNameScope.h" 39 40 #include "LowLevelInterpreter.h" 40 41 41 #include "StrongInlines.h" 42 42 #include <wtf/text/WTFString.h> … … 325 325 globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties. 326 326 327 JSValue value = JSFunction::create(exec, makeFunction(exec, function), scope);327 JSValue value = JSFunction::create(exec, FunctionExecutable::create(*m_globalData, function), scope); 328 328 int index = addGlobalVar( 329 329 function->ident(), IsVariable, … … 420 420 } 421 421 422 RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var. 423 422 424 const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack(); 423 425 const DeclarationStacks::VarStack& varStack = functionBody->varStack(); … … 457 459 458 460 codeBlock->m_numCapturedVars = codeBlock->m_numVars; 461 459 462 m_firstLazyFunction = codeBlock->m_numVars; 460 463 for (size_t i = 0; i < functionStack.size(); ++i) { … … 497 500 498 501 preserveLastVar(); 502 503 // We declare the callee's name last because it should lose to a var, function, and/or parameter declaration. 504 addCallee(functionBody, calleeRegister); 499 505 500 506 if (isConstructor()) { … … 550 556 const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack(); 551 557 for (size_t i = 0; i < functionStack.size(); ++i) 552 m_codeBlock->addFunctionDecl( makeFunction(m_globalData, functionStack[i]));558 m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i])); 553 559 554 560 const DeclarationStacks::VarStack& varStack = evalNode->varStack(); … … 573 579 instructions().append(reg->index()); 574 580 return reg; 581 } 582 583 RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode) 584 { 585 if (functionBodyNode->ident().isNull()) 586 return 0; 587 588 m_calleeRegister.setIndex(RegisterFile::Callee); 589 590 // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. 591 if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) { 592 emitOpcode(op_push_name_scope); 593 instructions().append(addConstant(functionBodyNode->ident())); 594 instructions().append(m_calleeRegister.index()); 595 instructions().append(ReadOnly | DontDelete); 596 597 // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime. 598 m_scope.set(*globalData(), 599 JSNameScope::create( 600 m_scope->globalObject()->globalExec(), 601 functionBodyNode->ident(), 602 jsUndefined(), 603 ReadOnly | DontDelete, 604 m_scope.get() 605 ) 606 ); 607 return 0; 608 } 609 610 if (!functionBodyNode->captures(functionBodyNode->ident())) 611 return &m_calleeRegister; 612 613 // Move the callee into the captured section of the stack. 614 return emitMove(addVar(), &m_calleeRegister); 615 } 616 617 void BytecodeGenerator::addCallee(FunctionBodyNode* functionBodyNode, RegisterID* calleeRegister) 618 { 619 if (functionBodyNode->ident().isNull()) 620 return; 621 622 // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. 623 if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) 624 return; 625 626 ASSERT(calleeRegister); 627 symbolTable().add(functionBodyNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly)); 575 628 } 576 629 … … 1831 1884 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function) 1832 1885 { 1833 return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl( makeFunction(m_globalData, function)), false);1886 return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, function)), false); 1834 1887 } 1835 1888 … … 1838 1891 FunctionOffsetMap::AddResult ptr = m_functionOffsets.add(function, 0); 1839 1892 if (ptr.isNewEntry) 1840 ptr.iterator->second = m_codeBlock->addFunctionDecl( makeFunction(m_globalData, function));1893 ptr.iterator->second = m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, function)); 1841 1894 return emitNewFunctionInternal(dst, ptr.iterator->second, true); 1842 1895 } … … 1863 1916 { 1864 1917 FunctionBodyNode* function = n->body(); 1865 unsigned index = m_codeBlock->addFunctionExpr( makeFunction(m_globalData, function));1918 unsigned index = m_codeBlock->addFunctionExpr(FunctionExecutable::create(*m_globalData, function)); 1866 1919 1867 1920 createActivationIfNecessary(); … … 2600 2653 return; 2601 2654 2602 RefPtr<RegisterID> error = emitLoad(newTemporary(), createTypeError(scope()->globalObject()->globalExec(), StrictModeReadonlyPropertyWriteError));2655 RefPtr<RegisterID> error = emitLoad(newTemporary(), JSValue(createTypeError(scope()->globalObject()->globalExec(), StrictModeReadonlyPropertyWriteError))); 2603 2656 emitThrow(error.get()); 2604 2657 } -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r127647 r127698 618 618 619 619 void addParameter(const Identifier&, int parameterIndex); 620 620 RegisterID* resolveCallee(FunctionBodyNode*); 621 void addCallee(FunctionBodyNode*, RegisterID*); 622 621 623 void preserveLastVar(); 622 624 bool shouldAvoidResolveGlobal(); … … 626 628 if (index >= 0) 627 629 return m_calleeRegisters[index]; 630 631 if (index == RegisterFile::Callee) 632 return m_calleeRegister; 628 633 629 634 ASSERT(m_parameters.size()); … … 637 642 unsigned addConstantBuffer(unsigned length); 638 643 639 FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)640 {641 return FunctionExecutable::create(exec, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());642 }643 644 FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)645 {646 return FunctionExecutable::create(*globalData, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());647 }648 649 644 JSString* addStringConstant(const Identifier&); 650 645 … … 717 712 RegisterID m_ignoredResultRegister; 718 713 RegisterID m_thisRegister; 714 RegisterID m_calleeRegister; 719 715 RegisterID* m_activationRegister; 720 716 SegmentedVector<RegisterID, 32> m_constantPoolRegisters; -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r127536 r127698 1244 1244 JSGlobalData& globalData = exec->globalData(); 1245 1245 NativeCallFrameTracer tracer(&globalData, exec); 1246 return static_cast<FunctionExecutable*>(functionExecutable)->make(exec, exec->scope());1246 return JSFunction::create(exec, static_cast<FunctionExecutable*>(functionExecutable), exec->scope()); 1247 1247 } 1248 1248 … … 1252 1252 FunctionExecutable* functionExecutable = 1253 1253 static_cast<FunctionExecutable*>(functionExecutableAsCell); 1254 JSFunction* function = functionExecutable->make(exec, exec->scope()); 1255 if (!functionExecutable->name().isNull()) { 1256 JSNameScope* functionScopeObject = 1257 JSNameScope::create( 1258 exec, functionExecutable->name(), function, ReadOnly | DontDelete); 1259 function->setScope(exec->globalData(), functionScopeObject); 1260 } 1261 return function; 1254 return JSFunction::create(exec, functionExecutable, exec->scope()); 1262 1255 } 1263 1256 -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r127505 r127698 1348 1348 FunctionExecutable* function = codeBlock->functionDecl(i); 1349 1349 PutPropertySlot slot; 1350 variableObject->methodTable()->put(variableObject, callFrame, function->name(), function->make(callFrame, scope), slot);1350 variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(callFrame, function, scope), slot); 1351 1351 } 1352 1352 } … … 4280 4280 JSFunction* func = function->make(callFrame, callFrame->scope()); 4281 4281 4282 /*4283 The Identifier in a FunctionExpression can be referenced from inside4284 the FunctionExpression's FunctionBody to allow the function to call4285 itself recursively. However, unlike in a FunctionDeclaration, the4286 Identifier in a FunctionExpression cannot be referenced from and4287 does not affect the scope enclosing the FunctionExpression.4288 */4289 if (!function->name().isNull()) {4290 JSNameScope* functionScopeObject = JSNameScope::create(callFrame, function->name(), func, ReadOnly | DontDelete);4291 func->setScope(*globalData, functionScopeObject);4292 }4293 4294 4282 callFrame->uncheckedR(dst) = JSValue(func); 4295 4283 -
trunk/Source/JavaScriptCore/jit/JITStubs.cpp
r127394 r127698 2142 2142 2143 2143 ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue()); 2144 return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scope());2144 return JSFunction::create(stackFrame.callFrame, stackFrame.args[0].function(), stackFrame.callFrame->scope()); 2145 2145 } 2146 2146 … … 2983 2983 2984 2984 FunctionExecutable* function = stackFrame.args[0].function(); 2985 JSFunction* func = function->make(callFrame, callFrame->scope());2985 JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope()); 2986 2986 ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue()); 2987 2988 /*2989 The Identifier in a FunctionExpression can be referenced from inside2990 the FunctionExpression's FunctionBody to allow the function to call2991 itself recursively. However, unlike in a FunctionDeclaration, the2992 Identifier in a FunctionExpression cannot be referenced from and2993 does not affect the scope enclosing the FunctionExpression.2994 */2995 if (!function->name().isNull()) {2996 JSNameScope* functionScopeObject = JSNameScope::create(callFrame, function->name(), func, ReadOnly | DontDelete);2997 func->setScope(callFrame->globalData(), functionScopeObject);2998 }2999 2987 3000 2988 return func; -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r127393 r127698 1261 1261 dataLog("Creating function!\n"); 1262 1262 #endif 1263 LLINT_RETURN( codeBlock->functionDecl(pc[2].u.operand)->make(exec, exec->scope()));1263 LLINT_RETURN(JSFunction::create(exec, codeBlock->functionDecl(pc[2].u.operand), exec->scope())); 1264 1264 } 1265 1265 … … 1269 1269 CodeBlock* codeBlock = exec->codeBlock(); 1270 1270 FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand); 1271 JSFunction* func = function->make(exec, exec->scope()); 1272 1273 if (!function->name().isNull()) { 1274 JSNameScope* functionScopeObject = JSNameScope::create(exec, function->name(), func, ReadOnly | DontDelete); 1275 func->setScope(globalData, functionScopeObject); 1276 } 1271 JSFunction* func = JSFunction::create(exec, function, exec->scope()); 1277 1272 1278 1273 LLINT_RETURN(func); -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r127191 r127698 41 41 42 42 template <typename LexerType> 43 Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode)43 Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode) 44 44 : m_globalData(globalData) 45 45 , m_source(&source) … … 72 72 scope->declareParameter(¶meters->at(i)); 73 73 } 74 if (!name.isNull()) 75 scope->declareCallee(&name); 74 76 next(); 75 77 m_lexer->setLastLineNumber(tokenLine()); -
trunk/Source/JavaScriptCore/parser/Parser.h
r127574 r127698 209 209 bool isFunctionBoundary() { return m_isFunctionBoundary; } 210 210 211 void declareCallee(const Identifier* ident) 212 { 213 m_declaredVariables.add(ident->ustring().impl()); 214 } 215 211 216 bool declareVariable(const Identifier* ident) 212 217 { … … 383 388 384 389 public: 385 Parser(JSGlobalData*, const SourceCode&, FunctionParameters*, JSParserStrictness, JSParserMode);390 Parser(JSGlobalData*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode); 386 391 ~Parser(); 387 392 … … 1021 1026 1022 1027 template <class ParsedNode> 1023 PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, Debugger* debugger, ExecState* execState, JSObject** exception)1028 PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, Debugger* debugger, ExecState* execState, JSObject** exception) 1024 1029 { 1025 1030 SamplingRegion samplingRegion("Parsing"); … … 1028 1033 1029 1034 if (source.provider()->data()->is8Bit()) { 1030 Parser< Lexer<LChar> > parser(globalData, source, parameters, strictness, parserMode);1035 Parser< Lexer<LChar> > parser(globalData, source, parameters, name, strictness, parserMode); 1031 1036 return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception); 1032 1037 } 1033 Parser< Lexer<UChar> > parser(globalData, source, parameters, strictness, parserMode);1038 Parser< Lexer<UChar> > parser(globalData, source, parameters, name, strictness, parserMode); 1034 1039 return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception); 1035 1040 } -
trunk/Source/JavaScriptCore/runtime/Executable.cpp
r127505 r127698 134 134 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) }; 135 135 136 FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)137 : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, inStrictContext)136 FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, FunctionBodyNode* node) 137 : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, node->source(), node->isStrictMode()) 138 138 , m_numCapturedVariables(0) 139 , m_forceUsesArguments(forceUsesArguments) 140 , m_parameters(parameters) 141 , m_name(name) 142 , m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName) 143 { 144 } 145 146 FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext) 147 : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext) 148 , m_numCapturedVariables(0) 149 , m_forceUsesArguments(forceUsesArguments) 150 , m_parameters(parameters) 151 , m_name(name) 152 , m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName) 153 { 139 , m_forceUsesArguments(node->usesArguments()) 140 , m_parameters(node->parameters()) 141 , m_name(node->ident()) 142 , m_inferredName(node->inferredName().isNull() ? globalData.propertyNames->emptyIdentifier : node->inferredName()) 143 { 144 m_firstLine = node->lineNo(); 145 m_lastLine = node->lastLine(); 154 146 } 155 147 … … 211 203 if (!lexicalGlobalObject->evalEnabled()) 212 204 return throwError(exec, createEvalError(exec, ASCIILiteral("Eval is disabled"))); 213 RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);205 RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception); 214 206 if (!evalNode) { 215 207 ASSERT(exception); … … 294 286 JSGlobalData* globalData = &exec->globalData(); 295 287 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); 296 RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);288 RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception); 297 289 if (programNode) 298 290 return 0; … … 336 328 m_programCodeBlock = newCodeBlock.release(); 337 329 } else { 338 RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);330 RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception); 339 331 if (!programNode) { 340 332 ASSERT(exception); … … 479 471 JSGlobalData* globalData = scope->globalData(); 480 472 JSGlobalObject* globalObject = scope->globalObject(); 481 RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(globalData, globalObject, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, 0, 0, &exception); 473 RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>( 474 globalData, 475 globalObject, 476 m_source, 477 m_parameters.get(), 478 name(), 479 isStrictMode() ? JSParseStrict : JSParseNormal, 480 FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, 481 0, 482 0, 483 &exception 484 ); 482 485 483 486 if (!body) { … … 648 651 } 649 652 650 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)653 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) 651 654 { 652 655 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); 653 RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception);656 RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception); 654 657 if (!program) { 655 658 ASSERT(*exception); … … 657 660 } 658 661 659 // Uses of this function that would not result in a single function expression are invalid.662 // This function assumes an input string that would result in a single anonymous function expression. 660 663 StatementNode* exprStatement = program->singleStatement(); 661 664 ASSERT(exprStatement); … … 666 669 FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); 667 670 ASSERT(body); 668 669 return FunctionExecutable::create(exec->globalData(), functionName, functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine()); 671 ASSERT(body->ident().isNull()); 672 673 FunctionExecutable* functionExecutable = FunctionExecutable::create(exec->globalData(), body); 674 functionExecutable->m_nameValue.set(exec->globalData(), functionExecutable, jsString(&exec->globalData(), name.ustring())); 675 return functionExecutable; 670 676 } 671 677 -
trunk/Source/JavaScriptCore/runtime/Executable.h
r127374 r127698 540 540 typedef ScriptExecutable Base; 541 541 542 static FunctionExecutable* create( ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)543 { 544 FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>( *exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);545 executable->finishCreation( exec->globalData(), name, firstLine, lastLine);542 static FunctionExecutable* create(JSGlobalData& globalData, FunctionBodyNode* node) 543 { 544 FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, node); 545 executable->finishCreation(globalData); 546 546 return executable; 547 547 } 548 549 static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) 550 { 551 FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext); 552 executable->finishCreation(globalData, name, firstLine, lastLine); 553 return executable; 554 } 548 static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception); 555 549 556 550 static void destroy(JSCell*); 557 551 558 JSFunction* make(ExecState* exec, JSScope* scope)559 {560 return JSFunction::create(exec, this, scope);561 }562 563 552 // Returns either call or construct bytecode. This can be appropriate 564 553 // for answering questions that that don't vary between call and construct -- … … 709 698 void clearCodeIfNotCompiling(); 710 699 static void visitChildren(JSCell*, SlotVisitor&); 711 static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);712 700 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) 713 701 { … … 722 710 723 711 protected: 724 void finishCreation(JSGlobalData& globalData , const Identifier& name, int firstLine, int lastLine)712 void finishCreation(JSGlobalData& globalData) 725 713 { 726 714 Base::finishCreation(globalData); 727 m_firstLine = firstLine; 728 m_lastLine = lastLine; 729 m_nameValue.set(globalData, this, jsString(&globalData, name.ustring())); 715 m_nameValue.set(globalData, this, jsString(&globalData, name().ustring())); 730 716 } 731 717 732 718 private: 733 FunctionExecutable(JSGlobalData&, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool); 734 FunctionExecutable(ExecState*, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool); 719 FunctionExecutable(JSGlobalData&, FunctionBodyNode*); 735 720 736 721 JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX); -
trunk/Source/JavaScriptCore/runtime/JSNameScope.h
r127363 r127698 39 39 static JSNameScope* create(ExecState* exec, const Identifier& identifier, JSValue value, unsigned attributes) 40 40 { 41 JSNameScope* scopeObject = new (NotNull, allocateCell<JSNameScope>(*exec->heap())) JSNameScope(exec); 41 JSNameScope* scopeObject = new (NotNull, allocateCell<JSNameScope>(*exec->heap())) JSNameScope(exec, exec->scope()); 42 scopeObject->finishCreation(exec, identifier, value, attributes); 43 return scopeObject; 44 } 45 46 static JSNameScope* create(ExecState* exec, const Identifier& identifier, JSValue value, unsigned attributes, JSScope* next) 47 { 48 JSNameScope* scopeObject = new (NotNull, allocateCell<JSNameScope>(*exec->heap())) JSNameScope(exec, next); 42 49 scopeObject->finishCreation(exec, identifier, value, attributes); 43 50 return scopeObject; … … 65 72 66 73 private: 67 JSNameScope(ExecState* exec )74 JSNameScope(ExecState* exec, JSScope* next) 68 75 : Base( 69 76 exec->globalData(), 70 77 exec->lexicalGlobalObject()->nameScopeStructure(), 71 78 reinterpret_cast<Register*>(&m_registerStore + 1), 72 exec->scope()79 next 73 80 ) 74 81 {
Note: See TracChangeset
for help on using the changeset viewer.