<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[180506] trunk/Source/JavaScriptCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/180506">180506</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-02-23 10:13:41 -0800 (Mon, 23 Feb 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Function name scope is only created on the function instance that triggered parsing rather than on every function instance that needs it
https://bugs.webkit.org/show_bug.cgi?id=141881
Reviewed by Michael Saboff.
Previously we only created the function name scope in a way that made it visible to the
function that triggered parsing/linking of the executable/codeBlock, and to the linker for
that code block. This was sort of the bare minimum for the feature to appear to work right to
synthetic tests.
There are two valid "times" to create the function name scope. Either it's created for each
JSFunction instance that needs a name scope, or it's created for each execution of such a
JSFunction. This change chooses the latter, because it happens to be the easiest to implement
with what we have right now. I opened a bug for optimizing this if we ever need to:
https://bugs.webkit.org/show_bug.cgi?id=141887.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setUpCall):
* runtime/ArrayPrototype.cpp:
(JSC::isNumericCompareFunction):
* runtime/Executable.cpp:
(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::prepareForExecutionImpl):
(JSC::FunctionExecutable::FunctionExecutable):
* runtime/Executable.h:
(JSC::ScriptExecutable::prepareForExecution):
* runtime/JSFunction.cpp:
(JSC::JSFunction::addNameScopeIfNeeded): Deleted.
* runtime/JSFunction.h:
* tests/stress/function-name-scope.js: Added.
(check.verify):
(check):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArrayPrototypecpp">trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeExecutablecpp">trunk/Source/JavaScriptCore/runtime/Executable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeExecutableh">trunk/Source/JavaScriptCore/runtime/Executable.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSFunctioncpp">trunk/Source/JavaScriptCore/runtime/JSFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSFunctionh">trunk/Source/JavaScriptCore/runtime/JSFunction.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressfunctionnamescopejs">trunk/Source/JavaScriptCore/tests/stress/function-name-scope.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -1,5 +1,48 @@
</span><span class="cx"> 2015-02-22 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><ins>+ Function name scope is only created on the function instance that triggered parsing rather than on every function instance that needs it
+ https://bugs.webkit.org/show_bug.cgi?id=141881
+
+ Reviewed by Michael Saboff.
+
+ Previously we only created the function name scope in a way that made it visible to the
+ function that triggered parsing/linking of the executable/codeBlock, and to the linker for
+ that code block. This was sort of the bare minimum for the feature to appear to work right to
+ synthetic tests.
+
+ There are two valid "times" to create the function name scope. Either it's created for each
+ JSFunction instance that needs a name scope, or it's created for each execution of such a
+ JSFunction. This change chooses the latter, because it happens to be the easiest to implement
+ with what we have right now. I opened a bug for optimizing this if we ever need to:
+ https://bugs.webkit.org/show_bug.cgi?id=141887.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::execute):
+ (JSC::Interpreter::executeCall):
+ (JSC::Interpreter::executeConstruct):
+ (JSC::Interpreter::prepareForRepeatCall):
+ * jit/JITOperations.cpp:
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::setUpCall):
+ * runtime/ArrayPrototype.cpp:
+ (JSC::isNumericCompareFunction):
+ * runtime/Executable.cpp:
+ (JSC::ScriptExecutable::newCodeBlockFor):
+ (JSC::ScriptExecutable::prepareForExecutionImpl):
+ (JSC::FunctionExecutable::FunctionExecutable):
+ * runtime/Executable.h:
+ (JSC::ScriptExecutable::prepareForExecution):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::addNameScopeIfNeeded): Deleted.
+ * runtime/JSFunction.h:
+ * tests/stress/function-name-scope.js: Added.
+ (check.verify):
+ (check):
+
+2015-02-22 Filip Pizlo <fpizlo@apple.com>
+
</ins><span class="cx"> Crash in DFGFrozenValue
</span><span class="cx"> https://bugs.webkit.org/show_bug.cgi?id=141883
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2009, 2012, 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved.
</ins><span class="cx"> * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
</span><span class="cx"> * Copyright (C) 2012 Igalia, S.L.
</span><span class="cx"> *
</span><span class="lines">@@ -208,6 +208,19 @@
</span><span class="cx"> emitOpcode(op_enter);
</span><span class="cx">
</span><span class="cx"> allocateAndEmitScope();
</span><ins>+
+ if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode())
+ && functionNameScopeIsDynamic(codeBlock->usesEval(), codeBlock->isStrictMode())) {
+ // When we do this, we should make our local scope stack know about the function name symbol
+ // table. Currently this works because bytecode linking creates a phony name scope.
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141885
+ // Also, we could create the scope once per JSFunction instance that needs it. That wouldn't
+ // be any more correct, but it would be more performant.
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141887
+ RegisterID calleeRegister;
+ calleeRegister.setIndex(JSStack::Callee);
+ emitPushFunctionNameScope(m_scopeRegister, functionNode->ident(), &calleeRegister, ReadOnly | DontDelete);
+ }
</ins><span class="cx">
</span><span class="cx"> if (m_codeBlock->needsFullScopeChain() || m_shouldEmitDebugHooks) {
</span><span class="cx"> m_lexicalEnvironmentRegister = addVar();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2009, 2010, 2012-2015 Apple Inc. All rights reserved.
</ins><span class="cx"> * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
</span><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -830,7 +830,7 @@
</span><span class="cx"> if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope))
</span><span class="cx"> return checkedReturn(callFrame->vm().throwException(callFrame, error));
</span><span class="cx">
</span><del>- if (JSObject* error = program->prepareForExecution(callFrame, nullptr, &scope, CodeForCall))
</del><ins>+ if (JSObject* error = program->prepareForExecution(callFrame, nullptr, scope, CodeForCall))
</ins><span class="cx"> return checkedReturn(callFrame->vm().throwException(callFrame, error));
</span><span class="cx">
</span><span class="cx"> ProgramCodeBlock* codeBlock = program->codeBlock();
</span><span class="lines">@@ -890,7 +890,7 @@
</span><span class="cx">
</span><span class="cx"> if (isJSCall) {
</span><span class="cx"> // Compile the callee:
</span><del>- JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(function), &scope, CodeForCall);
</del><ins>+ JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(function), scope, CodeForCall);
</ins><span class="cx"> if (UNLIKELY(!!compileError)) {
</span><span class="cx"> return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
</span><span class="cx"> }
</span><span class="lines">@@ -961,7 +961,7 @@
</span><span class="cx">
</span><span class="cx"> if (isJSConstruct) {
</span><span class="cx"> // Compile the callee:
</span><del>- JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(constructor), &scope, CodeForConstruct);
</del><ins>+ JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(constructor), scope, CodeForConstruct);
</ins><span class="cx"> if (UNLIKELY(!!compileError)) {
</span><span class="cx"> return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
</span><span class="cx"> }
</span><span class="lines">@@ -1014,7 +1014,7 @@
</span><span class="cx"> return CallFrameClosure();
</span><span class="cx">
</span><span class="cx"> // Compile the callee:
</span><del>- JSObject* error = functionExecutable->prepareForExecution(callFrame, function, &scope, CodeForCall);
</del><ins>+ JSObject* error = functionExecutable->prepareForExecution(callFrame, function, scope, CodeForCall);
</ins><span class="cx"> if (error) {
</span><span class="cx"> callFrame->vm().throwException(callFrame, error);
</span><span class="cx"> return CallFrameClosure();
</span><span class="lines">@@ -1097,7 +1097,7 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- JSObject* compileError = eval->prepareForExecution(callFrame, nullptr, &scope, CodeForCall);
</del><ins>+ JSObject* compileError = eval->prepareForExecution(callFrame, nullptr, scope, CodeForCall);
</ins><span class="cx"> if (UNLIKELY(!!compileError))
</span><span class="cx"> return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
</span><span class="cx"> EvalCodeBlock* codeBlock = eval->codeBlock();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -695,7 +695,7 @@
</span><span class="cx"> codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, registers);
</span><span class="cx"> else {
</span><span class="cx"> FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
</span><del>- JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, &scope, kind);
</del><ins>+ JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
</ins><span class="cx"> if (error) {
</span><span class="cx"> throwStackOverflowError(exec);
</span><span class="cx"> return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</span><span class="lines">@@ -753,7 +753,7 @@
</span><span class="cx"> ExecutableBase* executable = function->executable();
</span><span class="cx"> if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
</span><span class="cx"> FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
</span><del>- JSObject* error = functionExecutable->prepareForExecution(execCallee, function, &scope, kind);
</del><ins>+ JSObject* error = functionExecutable->prepareForExecution(execCallee, function, scope, kind);
</ins><span class="cx"> if (error) {
</span><span class="cx"> exec->vm().throwException(exec, error);
</span><span class="cx"> return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -1094,7 +1094,7 @@
</span><span class="cx"> codePtr = executable->entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired);
</span><span class="cx"> else {
</span><span class="cx"> FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
</span><del>- JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, &scope, kind);
</del><ins>+ JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
</ins><span class="cx"> if (error)
</span><span class="cx"> LLINT_CALL_THROW(exec, error);
</span><span class="cx"> codeBlock = functionExecutable->codeBlockFor(kind);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArrayPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx"> * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><del>- * Copyright (C) 2003, 2007, 2008, 2009, 2011, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2003, 2007, 2008, 2009, 2011, 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx"> * Copyright (C) 2003 Peter Kelly (pmk@post.com)
</span><span class="cx"> * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
</span><span class="cx"> *
</span><span class="lines">@@ -78,7 +78,7 @@
</span><span class="cx"> FunctionExecutable* executable = callData.js.functionExecutable;
</span><span class="cx"> JSScope* scope = callData.js.scope;
</span><span class="cx">
</span><del>- JSObject* error = executable->prepareForExecution(exec, jsCast<JSFunction*>(function), &scope, CodeForCall);
</del><ins>+ JSObject* error = executable->prepareForExecution(exec, jsCast<JSFunction*>(function), scope, CodeForCall);
</ins><span class="cx"> if (error)
</span><span class="cx"> return false;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Executable.cpp (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Executable.cpp        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/runtime/Executable.cpp        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2009, 2010, 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -30,8 +30,9 @@
</span><span class="cx"> #include "CodeBlock.h"
</span><span class="cx"> #include "DFGDriver.h"
</span><span class="cx"> #include "JIT.h"
</span><ins>+#include "JSCInlines.h"
+#include "JSFunctionNameScope.h"
</ins><span class="cx"> #include "LLIntEntrypoint.h"
</span><del>-#include "JSCInlines.h"
</del><span class="cx"> #include "Parser.h"
</span><span class="cx"> #include "ProfilerDatabase.h"
</span><span class="cx"> #include "TypeProfiler.h"
</span><span class="lines">@@ -198,9 +199,9 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> PassRefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
</span><del>- CodeSpecializationKind kind, JSFunction* function, JSScope** scope, JSObject*& exception)
</del><ins>+ CodeSpecializationKind kind, JSFunction* function, JSScope* scope, JSObject*& exception)
</ins><span class="cx"> {
</span><del>- VM* vm = (*scope)->vm();
</del><ins>+ VM* vm = scope->vm();
</ins><span class="cx">
</span><span class="cx"> ASSERT(vm->heap.isDeferred());
</span><span class="cx"> ASSERT(startColumn() != UINT_MAX);
</span><span class="lines">@@ -212,7 +213,7 @@
</span><span class="cx"> RELEASE_ASSERT(!executable->m_evalCodeBlock);
</span><span class="cx"> RELEASE_ASSERT(!function);
</span><span class="cx"> return adoptRef(new EvalCodeBlock(
</span><del>- executable, executable->m_unlinkedEvalCodeBlock.get(), *scope,
</del><ins>+ executable, executable->m_unlinkedEvalCodeBlock.get(), scope,
</ins><span class="cx"> executable->source().provider()));
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -222,7 +223,7 @@
</span><span class="cx"> RELEASE_ASSERT(!executable->m_programCodeBlock);
</span><span class="cx"> RELEASE_ASSERT(!function);
</span><span class="cx"> return adoptRef(new ProgramCodeBlock(
</span><del>- executable, executable->m_unlinkedProgramCodeBlock.get(), *scope,
</del><ins>+ executable, executable->m_unlinkedProgramCodeBlock.get(), scope,
</ins><span class="cx"> executable->source().provider(), executable->source().startColumn()));
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -230,7 +231,7 @@
</span><span class="cx"> RELEASE_ASSERT(function);
</span><span class="cx"> FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
</span><span class="cx"> RELEASE_ASSERT(!executable->codeBlockFor(kind));
</span><del>- JSGlobalObject* globalObject = (*scope)->globalObject();
</del><ins>+ JSGlobalObject* globalObject = scope->globalObject();
</ins><span class="cx"> ParserError error;
</span><span class="cx"> DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
</span><span class="cx"> ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
</span><span class="lines">@@ -247,10 +248,13 @@
</span><span class="cx">
</span><span class="cx"> // Parsing reveals whether our function uses features that require a separate function name object in the scope chain.
</span><span class="cx"> // Be sure to add this scope before linking the bytecode because this scope will change the resolution depth of non-local variables.
</span><del>- if (!executable->m_didParseForTheFirstTime) {
- executable->m_didParseForTheFirstTime = true;
- function->addNameScopeIfNeeded(*vm);
- *scope = function->scope();
</del><ins>+ if (functionNameIsInScope(executable->name(), executable->functionMode())
+ && functionNameScopeIsDynamic(executable->usesEval(), executable->isStrictMode())) {
+ // We shouldn't have to do this. But we do, because bytecode linking requires a real scope
+ // chain.
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141885
+ scope = JSFunctionNameScope::create(
+ *vm, scope->globalObject(), scope, executable->name(), function, ReadOnly | DontDelete);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> SourceProvider* provider = executable->source().provider();
</span><span class="lines">@@ -258,7 +262,7 @@
</span><span class="cx"> unsigned startColumn = executable->source().startColumn();
</span><span class="cx">
</span><span class="cx"> return adoptRef(new FunctionCodeBlock(
</span><del>- executable, unlinkedCodeBlock, *scope, provider, sourceOffset, startColumn));
</del><ins>+ executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
</span><span class="lines">@@ -314,7 +318,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> JSObject* ScriptExecutable::prepareForExecutionImpl(
</span><del>- ExecState* exec, JSFunction* function, JSScope** scope, CodeSpecializationKind kind)
</del><ins>+ ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
</ins><span class="cx"> {
</span><span class="cx"> VM& vm = exec->vm();
</span><span class="cx"> DeferGC deferGC(vm.heap);
</span><span class="lines">@@ -392,7 +396,6 @@
</span><span class="cx"> : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
</span><span class="cx"> , m_unlinkedExecutable(vm, this, unlinkedExecutable)
</span><span class="cx"> , m_bodyIncludesBraces(bodyIncludesBraces)
</span><del>- , m_didParseForTheFirstTime(false)
</del><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT(!source.isNull());
</span><span class="cx"> ASSERT(source.length());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Executable.h (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Executable.h        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/runtime/Executable.h        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2009, 2010, 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2009, 2010, 2013-2015 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -397,10 +397,10 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void installCode(CodeBlock*);
</span><del>- PassRefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope**, JSObject*& exception);
</del><ins>+ PassRefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
</ins><span class="cx"> PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
</span><span class="cx">
</span><del>- JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope** scope, CodeSpecializationKind kind)
</del><ins>+ JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
</ins><span class="cx"> {
</span><span class="cx"> if (hasJITCodeFor(kind))
</span><span class="cx"> return 0;
</span><span class="lines">@@ -410,7 +410,7 @@
</span><span class="cx"> template <typename Functor> void forEachCodeBlock(Functor&&);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope**, CodeSpecializationKind);
</del><ins>+ JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind);
</ins><span class="cx">
</span><span class="cx"> protected:
</span><span class="cx"> void finishCreation(VM& vm)
</span><span class="lines">@@ -662,7 +662,6 @@
</span><span class="cx"> RefPtr<FunctionCodeBlock> m_codeBlockForCall;
</span><span class="cx"> RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
</span><span class="cx"> bool m_bodyIncludesBraces;
</span><del>- bool m_didParseForTheFirstTime;
</del><span class="cx"> RefPtr<TypeSet> m_returnStatementTypeSet;
</span><span class="cx"> };
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSFunction.cpp (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -35,7 +35,6 @@
</span><span class="cx"> #include "JSArray.h"
</span><span class="cx"> #include "JSBoundFunction.h"
</span><span class="cx"> #include "JSFunctionInlines.h"
</span><del>-#include "JSFunctionNameScope.h"
</del><span class="cx"> #include "JSGlobalObject.h"
</span><span class="cx"> #include "JSNotAnObject.h"
</span><span class="cx"> #include "Interpreter.h"
</span><span class="lines">@@ -109,16 +108,6 @@
</span><span class="cx"> putDirect(vm, vm.propertyNames->length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JSFunction::addNameScopeIfNeeded(VM& vm)
-{
- FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_executable.get());
- if (!functionNameIsInScope(executable->name(), executable->functionMode()))
- return;
- if (!functionNameScopeIsDynamic(executable->usesEval(), executable->isStrictMode()))
- return;
- setScope(vm, JSFunctionNameScope::create(vm, scope()->globalObject(), scope(), executable->name(), this, ReadOnly | DontDelete));
-}
-
</del><span class="cx"> JSFunction* JSFunction::createBuiltinFunction(VM& vm, FunctionExecutable* executable, JSGlobalObject* globalObject)
</span><span class="cx"> {
</span><span class="cx"> JSFunction* function = create(vm, executable, globalObject);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSFunctionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSFunction.h (180505 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSFunction.h        2015-02-23 18:03:49 UTC (rev 180505)
+++ trunk/Source/JavaScriptCore/runtime/JSFunction.h        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx"> * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><del>- * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2015 Apple Inc. All rights reserved.
</ins><span class="cx"> * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
</span><span class="cx"> * Copyright (C) 2007 Maks Orlovich
</span><span class="cx"> *
</span><span class="lines">@@ -76,8 +76,6 @@
</span><span class="cx"> JS_EXPORT_PRIVATE String displayName(ExecState*);
</span><span class="cx"> const String calculatedDisplayName(ExecState*);
</span><span class="cx">
</span><del>- void addNameScopeIfNeeded(VM&);
-
</del><span class="cx"> ExecutableBase* executable() const { return m_executable.get(); }
</span><span class="cx">
</span><span class="cx"> // To call either of these methods include Executable.h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressfunctionnamescopejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/function-name-scope.js (0 => 180506)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/function-name-scope.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/function-name-scope.js        2015-02-23 18:13:41 UTC (rev 180506)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+function foo() {
+ return function bar(str) {
+ var barBefore = bar;
+ var result = eval(str);
+ return [
+ barBefore,
+ bar,
+ function () {
+ return bar;
+ },
+ result
+ ];
+ }
+}
+
+function check() {
+ var bar = foo();
+
+ function verify(result, barAfter, evalResult) {
+ if (result[0] !== bar)
+ throw "Error: bad first entry: " + result[0];
+ if (result[1] !== barAfter)
+ throw "Error: bad first entry: " + result[1];
+ var subResult = result[2]();
+ if (subResult !== barAfter)
+ throw "Error: bad second entry: " + result[2] + "; returned: " + subResult;
+ if (result[3] !== evalResult)
+ throw "Error: bad third entry: " + result[3] + "; expected: " + evalResult;
+ }
+
+ verify(bar("42"), bar, 42);
+ verify(bar("bar"), bar, bar);
+ verify(bar("var bar = 42; function fuzz() { return bar; }; fuzz()"), 42, 42);
+}
+
+// Execute check() more than once. At the time that we wrote this regression test, trunk would fail on
+// the second execution. Executing 100 times would also gives us some optimizing JIT coverage.
+for (var i = 0; i < 100; ++i)
+ check();
+
</ins></span></pre>
</div>
</div>
</body>
</html>