Commit cbc86179 authored by darin@apple.com's avatar darin@apple.com

JavaScriptCore: JavaScriptCore tweaks to get ready for the parser arena

https://bugs.webkit.org/show_bug.cgi?id=28243

Patch by Darin Adler <darin@apple.com> on 2009-08-13
Reviewed by David Levin.

Eliminate dependencies on Nodes.h outside JavaScriptCore,
and cut down on them inside JavaScriptCore.

Change regular expression parsing to use identifiers as
with other strings we parse.

Fix a couple things that are needed to use const Identifier
more, which will be part of the parser arena work.

* JavaScriptCore.exp: Resorted and updated.

* JavaScriptCore.xcodeproj/project.pbxproj: Changed
CollectorHeapIterator.h to be project-internal.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitPushNewScope): Added const.
* bytecompiler/BytecodeGenerator.h: Ditto.

* debugger/Debugger.cpp:
(JSC::Debugger::recompileAllJSFunctions): Moved this function
here from WebCore. Here is better since it uses so many internals.
Removed unimportant optimization for the no listener case.
* debugger/Debugger.h: Ditto. Also removed unneeded include
and tweaked formatting and comments.

* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::functionName): Call asFunction instead
of doing the unchecked static_cast.
(JSC::DebuggerCallFrame::calculatedFunctionName): Ditto.

* jit/JITStubs.cpp:
(JSC::op_call_JSFunction): Call isHostFunction on the body rather
than on the JSFunction.
(JSC::vm_lazyLinkCall): Ditto.
(JSC::op_construct_JSConstruct): Ditto.

* parser/Grammar.y: Changed callers to use new scanRegExp with
out arguments instead of relying on state in the Lexer. And
callers that just want to skip a regular expression to use
skipRegExp.

* parser/Lexer.cpp:
(JSC::Lexer::scanRegExp): Changed to use out arguments, and to
add a prefix argument so we can add in the "=" character as needed.
Also rewrote to streamline the logic a bit inspired by suggestions
by David Levin.
(JSC::Lexer::skipRegExp): Added. Version of the function above that
does not actually put the regular expression into a string.
(JSC::Lexer::clear): Removed code to clear m_pattern and m_flags.
* parser/Lexer.h: Changed scanRegExp to have out arguments. Added
skipRegExp. Eliminated pattern, flags, m_pattern, and m_flags.

* parser/NodeConstructors.h:
(JSC::RegExpNode::RegExpNode): Changed to take const Identifier&.
* parser/Nodes.cpp:
(JSC::RegExpNode::emitBytecode): Changed since m_pattern and
m_flags are now Identifier instead of UString.
(JSC::FunctionBodyNode::make): Moved this function here instead
of putting it in the JSFunction.h header.
* parser/Nodes.h: Changed RegExpNode to use Identifier.

* profiler/Profiler.cpp:
(JSC::Profiler::createCallIdentifier): Changed to use isHostFunction
on the body instead of on the JSFunction object.
* runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncToString): Ditto.

* runtime/JSFunction.cpp:
(JSC::JSFunction::isHostFunction): Moved here from header.
(JSC::JSFunction::isHostFunctionNonInline): Added.
(JSC::JSFunction::JSFunction): Removed unneeded initialization of
m_body to 0.
(JSC::JSFunction::setBody): Moved here from header.

* runtime/JSFunction.h: Removed unneeded includes. Moved private
constructor down to the private section. Made virtual functions
private. Removed unneeded overload of setBody and moved the body
of the function into the .cpp file. Changed assertions to use
the non-inline version of isHostFunction.

* runtime/PropertySlot.cpp:
(JSC::PropertySlot::functionGetter): Use asFunction instead
of doing the unchecked static_cast.

* wtf/SegmentedVector.h:
(WTF::SegmentedVector::isEmpty): Added.

WebCore: JavaScriptCore tweaks to get ready for the parser arena
https://bugs.webkit.org/show_bug.cgi?id=28243

Patch by Darin Adler <darin@apple.com> on 2009-08-13
Reviewed by David Levin.

* ForwardingHeaders/runtime/CollectorHeapIterator.h: Removed.

* WebCore.xcodeproj/project.pbxproj: Exposed a couple header
files as Private that are now needed to compile Mac WebKit.

* bindings/js/JSAudioConstructor.cpp:
* bindings/js/JSDOMBinding.cpp:
* bindings/js/JSDOMBinding.h:
* bindings/js/JSDOMWindowCustom.cpp:
* bindings/js/JSHTMLInputElementCustom.cpp:
* bindings/js/JSHistoryCustom.cpp:
* bindings/js/JSImageConstructor.cpp:
* bindings/js/JSLazyEventListener.cpp:
* bindings/js/JSLocationCustom.cpp:
* bindings/js/JSMessageChannelConstructor.cpp:
* bindings/js/JSOptionConstructor.cpp:
* bindings/js/JSWebSocketConstructor.cpp:
* bindings/js/JSWebSocketCustom.cpp:
* bindings/js/JSWorkerConstructor.cpp:
* bindings/js/JSXMLHttpRequestConstructor.cpp:
* bridge/jni/jni_jsobject.mm:
Updated includes.

* inspector/JavaScriptDebugServer.cpp:
(WebCore::JavaScriptDebugServer::sourceParsed):
Change to not assert if this is called with no listeners.
I don't think this was guaranteed before, and we now use
this code path when recompiling. Slightly less efficient,
but this is a one-time cost when turning on the debugger.
(WebCore::JavaScriptDebugServer::recompileAllJSFunctions):
Change to call Debugger::recompileAllJSFunctions.

WebKit/mac: * Plugins/Hosted/NetscapePluginInstanceProxy.mm: Updated includes.
* WebView/WebScriptDebugger.mm: Ditto.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@47236 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent e51d21d5
2009-08-13 Darin Adler <darin@apple.com>
Reviewed by David Levin.
JavaScriptCore tweaks to get ready for the parser arena
https://bugs.webkit.org/show_bug.cgi?id=28243
Eliminate dependencies on Nodes.h outside JavaScriptCore,
and cut down on them inside JavaScriptCore.
Change regular expression parsing to use identifiers as
with other strings we parse.
Fix a couple things that are needed to use const Identifier
more, which will be part of the parser arena work.
* JavaScriptCore.exp: Resorted and updated.
* JavaScriptCore.xcodeproj/project.pbxproj: Changed
CollectorHeapIterator.h to be project-internal.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitPushNewScope): Added const.
* bytecompiler/BytecodeGenerator.h: Ditto.
* debugger/Debugger.cpp:
(JSC::Debugger::recompileAllJSFunctions): Moved this function
here from WebCore. Here is better since it uses so many internals.
Removed unimportant optimization for the no listener case.
* debugger/Debugger.h: Ditto. Also removed unneeded include
and tweaked formatting and comments.
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::functionName): Call asFunction instead
of doing the unchecked static_cast.
(JSC::DebuggerCallFrame::calculatedFunctionName): Ditto.
* jit/JITStubs.cpp:
(JSC::op_call_JSFunction): Call isHostFunction on the body rather
than on the JSFunction.
(JSC::vm_lazyLinkCall): Ditto.
(JSC::op_construct_JSConstruct): Ditto.
* parser/Grammar.y: Changed callers to use new scanRegExp with
out arguments instead of relying on state in the Lexer. And
callers that just want to skip a regular expression to use
skipRegExp.
* parser/Lexer.cpp:
(JSC::Lexer::scanRegExp): Changed to use out arguments, and to
add a prefix argument so we can add in the "=" character as needed.
Also rewrote to streamline the logic a bit inspired by suggestions
by David Levin.
(JSC::Lexer::skipRegExp): Added. Version of the function above that
does not actually put the regular expression into a string.
(JSC::Lexer::clear): Removed code to clear m_pattern and m_flags.
* parser/Lexer.h: Changed scanRegExp to have out arguments. Added
skipRegExp. Eliminated pattern, flags, m_pattern, and m_flags.
* parser/NodeConstructors.h:
(JSC::RegExpNode::RegExpNode): Changed to take const Identifier&.
* parser/Nodes.cpp:
(JSC::RegExpNode::emitBytecode): Changed since m_pattern and
m_flags are now Identifier instead of UString.
(JSC::FunctionBodyNode::make): Moved this function here instead
of putting it in the JSFunction.h header.
* parser/Nodes.h: Changed RegExpNode to use Identifier.
* profiler/Profiler.cpp:
(JSC::Profiler::createCallIdentifier): Changed to use isHostFunction
on the body instead of on the JSFunction object.
* runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncToString): Ditto.
* runtime/JSFunction.cpp:
(JSC::JSFunction::isHostFunction): Moved here from header.
(JSC::JSFunction::isHostFunctionNonInline): Added.
(JSC::JSFunction::JSFunction): Removed unneeded initialization of
m_body to 0.
(JSC::JSFunction::setBody): Moved here from header.
* runtime/JSFunction.h: Removed unneeded includes. Moved private
constructor down to the private section. Made virtual functions
private. Removed unneeded overload of setBody and moved the body
of the function into the .cpp file. Changed assertions to use
the non-inline version of isHostFunction.
* runtime/PropertySlot.cpp:
(JSC::PropertySlot::functionGetter): Use asFunction instead
of doing the unchecked static_cast.
* wtf/SegmentedVector.h:
(WTF::SegmentedVector::isEmpty): Added.
2009-08-13 Mark Rowe <mrowe@apple.com>
Rubber-stamped by Darin Adler.
......
......@@ -95,7 +95,6 @@ __ZN3JSC10Identifier24checkSameIdentifierTableEPNS_12JSGlobalDataEPNS_7UString3R
__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_9ExecStateEPNS_7UString3RepE
__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc
__ZN3JSC10JSFunction4infoE
__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
......@@ -196,8 +195,8 @@ __ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutProper
__ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_7JSValueE
__ZN3JSC6JSCell9getObjectEv
__ZN3JSC6JSCellnwEmPNS_9ExecStateE
__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
__ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
__ZN3JSC6JSLock12DropAllLocksD1Ev
__ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
__ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
......@@ -227,9 +226,9 @@ __ZN3JSC7UString6appendERKS0_
__ZN3JSC7UStringC1EPKc
__ZN3JSC7UStringC1EPKti
__ZN3JSC7UStringaSEPKc
__ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE
__ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
__ZN3JSC8DebuggerC2Ev
__ZN3JSC8DebuggerD2Ev
__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
......@@ -324,13 +323,13 @@ __ZN3WTF8CollatorC1EPKc
__ZN3WTF8CollatorD1Ev
__ZN3WTF8fastFreeEPv
__ZN3WTF9ByteArray6createEm
__ZNK3JSC10JSFunction23isHostFunctionNonInlineEv
__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
__ZNK3JSC12DateInstance7getTimeERdRi
__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
__ZNK3JSC12StringObject8toStringEPNS_9ExecStateE
__ZNK3JSC14JSGlobalObject14isDynamicScopeEv
__ZNK3JSC16FunctionBodyNode14isHostFunctionEv
__ZNK3JSC16InternalFunction9classInfoEv
__ZNK3JSC16JSVariableObject16isVariableObjectEv
......@@ -379,6 +378,7 @@ __ZTVN3JSC15JSWrapperObjectE
__ZTVN3JSC16InternalFunctionE
__ZTVN3JSC16JSVariableObjectE
__ZTVN3JSC17JSAPIValueWrapperE
__ZTVN3JSC8DebuggerE
__ZTVN3JSC8JSObjectE
__ZTVN3JSC8JSStringE
_jscore_fastmalloc_introspection
......
......@@ -95,7 +95,7 @@
14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD5A290A3E91F600BAF59C /* JSContextRef.cpp */; };
14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD5A2B0A3E91F600BAF59C /* JSValueRef.cpp */; };
14C5242B0F5355E900BA3D04 /* JITStubs.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A6581A0F4E36F4000150FD /* JITStubs.h */; settings = {ATTRIBUTES = (Private, ); }; };
14F3488F0E95EF8A003648BC /* CollectorHeapIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F3488E0E95EF8A003648BC /* CollectorHeapIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
14F3488F0E95EF8A003648BC /* CollectorHeapIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F3488E0E95EF8A003648BC /* CollectorHeapIterator.h */; settings = {ATTRIBUTES = (); }; };
180B9B080F16D94F009BDBC5 /* CurrentTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 180B9AF00F16C569009BDBC5 /* CurrentTime.h */; settings = {ATTRIBUTES = (Private, ); }; };
180B9BFE0F16E94D009BDBC5 /* CurrentTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 180B9AEF0F16C569009BDBC5 /* CurrentTime.cpp */; };
1C61516C0EBAC7A00031376F /* ProfilerServer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C61516A0EBAC7A00031376F /* ProfilerServer.mm */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; };
......
......@@ -1800,7 +1800,7 @@ void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
instructions().append(retAddrSrc->index());
}
void BytecodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value)
void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value)
{
ControlFlowContext context;
context.isFinallyBlock = false;
......
......@@ -318,7 +318,7 @@ namespace JSC {
RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); }
RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValue message);
void emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value);
void emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value);
RegisterID* emitPushScope(RegisterID* scope);
void emitPopScope();
......
......@@ -22,16 +22,13 @@
#include "config.h"
#include "Debugger.h"
#include "JSGlobalObject.h"
#include "CollectorHeapIterator.h"
#include "Interpreter.h"
#include "JSGlobalObject.h"
#include "Parser.h"
namespace JSC {
Debugger::Debugger()
{
}
Debugger::~Debugger()
{
HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end();
......@@ -53,6 +50,62 @@ void Debugger::detach(JSGlobalObject* globalObject)
globalObject->setDebugger(0);
}
void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
{
// If JavaScript is running, it's not safe to recompile, since we'll end
// up throwing away code that is live on the stack.
ASSERT(!globalData->dynamicGlobalObject);
if (globalData->dynamicGlobalObject)
return;
Vector<ProtectedPtr<JSFunction> > functions;
Heap::iterator heapEnd = globalData->heap.primaryHeapEnd();
for (Heap::iterator it = globalData->heap.primaryHeapBegin(); it != heapEnd; ++it) {
if ((*it)->isObject(&JSFunction::info)) {
JSFunction* function = asFunction(*it);
if (!function->body()->isHostFunction())
functions.append(function);
}
}
typedef HashMap<RefPtr<FunctionBodyNode>, RefPtr<FunctionBodyNode> > FunctionBodyMap;
typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;
FunctionBodyMap functionBodies;
SourceProviderMap sourceProviders;
size_t size = functions.size();
for (size_t i = 0; i < size; ++i) {
JSFunction* function = functions[i];
FunctionBodyNode* oldBody = function->body();
pair<FunctionBodyMap::iterator, bool> result = functionBodies.add(oldBody, 0);
if (!result.second) {
function->setBody(result.first->second);
continue;
}
ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec();
const SourceCode& sourceCode = oldBody->source();
RefPtr<FunctionBodyNode> newBody = globalData->parser->parse<FunctionBodyNode>(exec, 0, sourceCode);
ASSERT(newBody);
newBody->finishParsing(oldBody->copyParameters(), oldBody->parameterCount(), oldBody->ident());
result.first->second = newBody;
function->setBody(newBody.release());
if (function->scope().globalObject()->debugger() == this)
sourceProviders.add(sourceCode.provider(), exec);
}
// Call sourceParsed() after reparsing all functions because it will execute
// JavaScript in the inspector.
SourceProviderMap::const_iterator end = sourceProviders.end();
for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter)
sourceParsed(iter->second, SourceCode(iter->first), -1, 0);
}
JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
{
CallFrame* globalCallFrame = globalObject->globalExec();
......
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
* Copyright (C) 2008 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -22,40 +22,42 @@
#ifndef Debugger_h
#define Debugger_h
#include "Protect.h"
#include <wtf/HashSet.h>
namespace JSC {
class DebuggerCallFrame;
class ExecState;
class JSGlobalData;
class JSGlobalObject;
class JSValue;
class SourceCode;
class UString;
class Debugger {
public:
Debugger();
virtual ~Debugger();
void attach(JSGlobalObject*);
virtual void detach(JSGlobalObject*);
virtual void sourceParsed(ExecState*, const SourceCode&, int errorLine, const UString& errorMsg) = 0;
virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
virtual void callEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
virtual void returnEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
virtual void sourceParsed(ExecState*, const SourceCode&, int errorLineNumber, const UString& errorMessage) = 0;
virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
virtual void callEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
virtual void returnEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
virtual void willExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
virtual void didExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
virtual void willExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
virtual void didExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
void recompileAllJSFunctions(JSGlobalData*);
private:
HashSet<JSGlobalObject*> m_globalObjects;
};
// This method exists only for backwards compatibility with existing
// WebScriptDebugger clients
// This function exists only for backwards compatibility with existing WebScriptDebugger clients.
JSValue evaluateInGlobalCallFrame(const UString&, JSValue& exception, JSGlobalObject*);
} // namespace JSC
......
......@@ -41,7 +41,7 @@ const UString* DebuggerCallFrame::functionName() const
if (!m_callFrame->codeBlock())
return 0;
JSFunction* function = static_cast<JSFunction*>(m_callFrame->callee());
JSFunction* function = asFunction(m_callFrame->callee());
if (!function)
return 0;
return &function->name(&m_callFrame->globalData());
......@@ -52,7 +52,7 @@ UString DebuggerCallFrame::calculatedFunctionName() const
if (!m_callFrame->codeBlock())
return 0;
JSFunction* function = static_cast<JSFunction*>(m_callFrame->callee());
JSFunction* function = asFunction(m_callFrame->callee());
if (!function)
return 0;
return function->calculatedDisplayName(&m_callFrame->globalData());
......
......@@ -1480,12 +1480,12 @@ DEFINE_STUB_FUNCTION(void*, op_call_JSFunction)
#endif
JSFunction* function = asFunction(stackFrame.args[0].jsValue());
ASSERT(!function->isHostFunction());
FunctionBodyNode* body = function->body();
ASSERT(!body->isHostFunction());
ScopeChainNode* callDataScopeChain = function->scope().node();
body->jitCode(callDataScopeChain);
return &(body->generatedBytecode());
return &body->generatedBytecode();
}
DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck)
......@@ -1539,13 +1539,14 @@ DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
{
STUB_INIT_STACK_FRAME(stackFrame);
JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
JITCode& jitCode = callee->body()->generatedJITCode();
FunctionBodyNode* body = callee->body();
JITCode& jitCode = body->generatedJITCode();
CodeBlock* codeBlock = 0;
if (!callee->isHostFunction())
codeBlock = &callee->body()->bytecode(callee->scope().node());
if (!body->isHostFunction())
codeBlock = &body->bytecode(callee->scope().node());
else
codeBlock = &callee->body()->generatedBytecode();
codeBlock = &body->generatedBytecode();
CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress());
if (!callLinkInfo->seenOnce())
......@@ -1715,7 +1716,8 @@ DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct)
STUB_INIT_STACK_FRAME(stackFrame);
JSFunction* constructor = asFunction(stackFrame.args[0].jsValue());
if (constructor->isHostFunction()) {
FunctionBodyNode* body = constructor->body();
if (body && body->isHostFunction()) {
CallFrame* callFrame = stackFrame.callFrame;
CodeBlock* codeBlock = callFrame->codeBlock();
unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
......
......@@ -292,19 +292,23 @@ Literal:
| STRING { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StringNode(GLOBAL_DATA, *$1), 0, 1); }
| '/' /* regexp */ {
Lexer& l = *LEXER;
if (!l.scanRegExp())
const Identifier* pattern;
const Identifier* flags;
if (!l.scanRegExp(pattern, flags))
YYABORT;
RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, l.pattern(), l.flags());
int size = l.pattern().size() + 2; // + 2 for the two /'s
RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, *pattern, *flags);
int size = pattern->size() + 2; // + 2 for the two /'s
SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size);
$$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
}
| DIVEQUAL /* regexp with /= */ {
Lexer& l = *LEXER;
if (!l.scanRegExp())
const Identifier* pattern;
const Identifier* flags;
if (!l.scanRegExp(pattern, flags, '='))
YYABORT;
RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, "=" + l.pattern(), l.flags());
int size = l.pattern().size() + 2; // + 2 for the two /'s
RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, *pattern, *flags);
int size = pattern->size() + 2; // + 2 for the two /'s
SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size);
$$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
}
......@@ -1241,8 +1245,8 @@ Literal_NoNode:
| FALSETOKEN
| NUMBER { }
| STRING { }
| '/' /* regexp */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; }
| DIVEQUAL /* regexp with /= */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; }
| '/' /* regexp */ { if (!LEXER->skipRegExp()) YYABORT; }
| DIVEQUAL /* regexp with /= */ { if (!LEXER->skipRegExp()) YYABORT; }
;
Property_NoNode:
......
......@@ -908,45 +908,107 @@ returnError:
return -1;
}
bool Lexer::scanRegExp()
bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
{
ASSERT(m_buffer16.isEmpty());
bool lastWasEscape = false;
bool inBrackets = false;
if (patternPrefix) {
ASSERT(!isLineTerminator(patternPrefix));
ASSERT(patternPrefix != '/');
ASSERT(patternPrefix != '[');
record16(patternPrefix);
}
while (true) {
if (isLineTerminator(m_current) || m_current == -1)
return false;
if (m_current != '/' || lastWasEscape || inBrackets) {
// keep track of '[' and ']'
if (!lastWasEscape) {
if (m_current == '[' && !inBrackets)
inBrackets = true;
if (m_current == ']' && inBrackets)
inBrackets = false;
}
record16(m_current);
lastWasEscape = !lastWasEscape && m_current == '\\';
} else { // end of regexp
m_pattern = UString(m_buffer16);
int current = m_current;
if (isLineTerminator(current) || current == -1) {
m_buffer16.resize(0);
shift1();
break;
return false;
}
shift1();
if (current == '/' && !lastWasEscape && !inBrackets)
break;
record16(current);
if (lastWasEscape) {
lastWasEscape = false;
continue;
}
switch (current) {
case '[':
inBrackets = true;
break;
case ']':
inBrackets = false;
break;
case '\\':
lastWasEscape = true;
break;
}
}
pattern = makeIdentifier(m_buffer16.data(), m_buffer16.size());
m_buffer16.resize(0);
while (isIdentPart(m_current)) {
record16(m_current);
shift1();
}
m_flags = UString(m_buffer16);
flags = makeIdentifier(m_buffer16.data(), m_buffer16.size());
m_buffer16.resize(0);
return true;
}
bool Lexer::skipRegExp()
{
bool lastWasEscape = false;
bool inBrackets = false;
while (true) {
int current = m_current;
if (isLineTerminator(current) || current == -1)
return false;
shift1();
if (current == '/' && !lastWasEscape && !inBrackets)
break;
if (lastWasEscape) {
lastWasEscape = false;
continue;
}
switch (current) {
case '[':
inBrackets = true;
break;
case ']':
inBrackets = false;
break;
case '\\':
lastWasEscape = true;
break;
}
}
while (isIdentPart(m_current))
shift1();
return true;
}
void Lexer::clear()
{
m_identifiers.clear();
......@@ -961,9 +1023,6 @@ void Lexer::clear()
m_buffer16.swap(newBuffer16);
m_isReparsing = false;
m_pattern = UString();
m_flags = UString();
}
SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine)
......
......@@ -50,9 +50,8 @@ namespace JSC {
int lineNumber() const { return m_lineNumber; }
bool prevTerminator() const { return m_terminator; }
SourceCode sourceCode(int openBrace, int closeBrace, int firstLine);
bool scanRegExp();
const UString& pattern() const { return m_pattern; }
const UString& flags() const { return m_flags; }
bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0);
bool skipRegExp();
// Functions for use after parsing.
bool sawError() const { return m_error; }
......@@ -112,9 +111,6 @@ namespace JSC {
JSGlobalData* m_globalData;
UString m_pattern;
UString m_flags;
const HashTable m_keywordTable;
Vector<UChar> m_codeWithoutBOMs;
......
......@@ -89,7 +89,7 @@ namespace JSC {
{
}
inline RegExpNode::RegExpNode(JSGlobalData* globalData, const UString& pattern, const UString& flags)
inline RegExpNode::RegExpNode(JSGlobalData* globalData, const Identifier& pattern, const Identifier& flags)
: ExpressionNode(globalData)
, m_pattern(pattern)
, m_flags(flags)
......
......@@ -138,7 +138,7 @@ RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d
RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring());
if (!regExp->isValid())
return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
if (dst == generator.ignoredResult())
......@@ -2156,6 +2156,11 @@ Identifier* FunctionBodyNode::copyParameters()
return parameters;
}
JSFunction* FunctionBodyNode::make(ExecState* exec, ScopeChainNode* scopeChain)
{
return new (exec) JSFunction(exec, m_ident, this, scopeChain);
}
// ------------------------------ FuncDeclNode ---------------------------------
RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
......
......@@ -357,13 +357,13 @@ namespace JSC {
class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
public:
RegExpNode(JSGlobalData*, const UString& pattern, const UString& flags);
RegExpNode(JSGlobalData*, const Identifier& pattern, const Identifier& flags);
private:
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
UString m_pattern;
UString m_flags;
Identifier m_pattern;
Identifier m_flags;
};
class ThisNode : public ExpressionNode {
......
......@@ -134,20 +134,20 @@ void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startin
dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
}
CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValue function, const UString& defaultSourceURL, int defaultLineNumber)
CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber)
{
if (!function)
if (!functionValue)
return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
if (!function.isObject())
if (!functionValue.isObject())
return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
if (asObject(function)->inherits(&JSFunction::info)) {
JSFunction* func = asFunction(function);
if (!func->isHostFunction())
return createCallIdentifierFromFunctionImp(globalData, func);
if (asObject